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 :
55 : #include <gnutls/gnutls.h>
56 : #include <gnutls/crypto.h>
57 :
58 : extern char *optarg;
59 : extern int optind;
60 :
61 : fstring host, workgroup, share, password, username, myname;
62 : struct cli_credentials *torture_creds;
63 : static const char *sockops="TCP_NODELAY";
64 : int torture_nprocs=1;
65 : static int port_to_use=0;
66 : int torture_numops=100;
67 : int torture_blocksize=1024*1024;
68 : static int procnum; /* records process count number when forking */
69 : static struct cli_state *current_cli;
70 : static fstring randomfname;
71 : static bool use_oplocks;
72 : static bool use_level_II_oplocks;
73 : static const char *client_txt = "client_oplocks.txt";
74 : static bool disable_spnego;
75 : static bool use_kerberos;
76 : static bool force_dos_errors;
77 : static fstring multishare_conn_fname;
78 : static bool use_multishare_conn = False;
79 : static bool do_encrypt;
80 : static const char *local_path = NULL;
81 : static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
82 : char *test_filename;
83 :
84 : bool torture_showall = False;
85 :
86 : static double create_procs(bool (*fn)(int), bool *result);
87 :
88 : /********************************************************************
89 : Ensure a connection is encrypted.
90 : ********************************************************************/
91 :
92 202 : static bool force_cli_encryption(struct cli_state *c,
93 : const char *sharename)
94 : {
95 : uint16_t major, minor;
96 : uint32_t caplow, caphigh;
97 : NTSTATUS status;
98 :
99 202 : if (!SERVER_HAS_UNIX_CIFS(c)) {
100 0 : d_printf("Encryption required and "
101 : "server that doesn't support "
102 : "UNIX extensions - failing connect\n");
103 0 : return false;
104 : }
105 :
106 202 : status = cli_unix_extensions_version(c, &major, &minor, &caplow,
107 : &caphigh);
108 202 : if (!NT_STATUS_IS_OK(status)) {
109 0 : d_printf("Encryption required and "
110 : "can't get UNIX CIFS extensions "
111 : "version from server: %s\n", nt_errstr(status));
112 0 : return false;
113 : }
114 :
115 202 : if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
116 0 : d_printf("Encryption required and "
117 : "share %s doesn't support "
118 : "encryption.\n", sharename);
119 0 : return false;
120 : }
121 :
122 202 : status = cli_smb1_setup_encryption(c, torture_creds);
123 202 : if (!NT_STATUS_IS_OK(status)) {
124 0 : d_printf("Encryption required and "
125 : "setup failed with error %s.\n",
126 : nt_errstr(status));
127 0 : return false;
128 : }
129 :
130 202 : return true;
131 : }
132 :
133 :
134 76 : static struct cli_state *open_nbt_connection(void)
135 : {
136 : struct cli_state *c;
137 : NTSTATUS status;
138 76 : int flags = 0;
139 :
140 76 : if (disable_spnego) {
141 0 : flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
142 : }
143 :
144 76 : if (use_oplocks) {
145 0 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
146 : }
147 :
148 76 : if (use_level_II_oplocks) {
149 0 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
150 : }
151 :
152 76 : if (force_dos_errors) {
153 0 : flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
154 : }
155 :
156 76 : status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
157 : signing_state, flags, &c);
158 76 : if (!NT_STATUS_IS_OK(status)) {
159 0 : printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
160 0 : return NULL;
161 : }
162 :
163 76 : cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
164 :
165 76 : return c;
166 : }
167 :
168 : /****************************************************************************
169 : Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
170 : ****************************************************************************/
171 :
172 4 : static bool cli_bad_session_request(int fd,
173 : struct nmb_name *calling, struct nmb_name *called)
174 : {
175 : TALLOC_CTX *frame;
176 : uint8_t len_buf[4];
177 : struct iovec iov[3];
178 : ssize_t len;
179 : uint8_t *inbuf;
180 : int err;
181 4 : bool ret = false;
182 : uint8_t message_type;
183 : uint8_t error;
184 : struct tevent_context *ev;
185 : struct tevent_req *req;
186 :
187 4 : frame = talloc_stackframe();
188 :
189 4 : iov[0].iov_base = len_buf;
190 4 : iov[0].iov_len = sizeof(len_buf);
191 :
192 : /* put in the destination name */
193 :
194 4 : iov[1].iov_base = name_mangle(talloc_tos(), called->name,
195 4 : called->name_type);
196 4 : if (iov[1].iov_base == NULL) {
197 0 : goto fail;
198 : }
199 4 : iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
200 4 : talloc_get_size(iov[1].iov_base));
201 :
202 : /* and my name */
203 :
204 4 : iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
205 4 : calling->name_type);
206 4 : if (iov[2].iov_base == NULL) {
207 0 : goto fail;
208 : }
209 4 : iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
210 4 : talloc_get_size(iov[2].iov_base));
211 :
212 : /* Deliberately corrupt the name len (first byte) */
213 4 : *((uint8_t *)iov[2].iov_base) = 100;
214 :
215 : /* send a session request (RFC 1002) */
216 : /* setup the packet length
217 : * Remove four bytes from the length count, since the length
218 : * field in the NBT Session Service header counts the number
219 : * of bytes which follow. The cli_send_smb() function knows
220 : * about this and accounts for those four bytes.
221 : * CRH.
222 : */
223 :
224 4 : _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
225 4 : SCVAL(len_buf,0,0x81);
226 :
227 4 : len = write_data_iov(fd, iov, 3);
228 4 : if (len == -1) {
229 0 : goto fail;
230 : }
231 :
232 4 : ev = samba_tevent_context_init(frame);
233 4 : if (ev == NULL) {
234 0 : goto fail;
235 : }
236 4 : req = read_smb_send(frame, ev, fd);
237 4 : if (req == NULL) {
238 0 : goto fail;
239 : }
240 4 : if (!tevent_req_poll(req, ev)) {
241 0 : goto fail;
242 : }
243 4 : len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
244 4 : if (len == -1) {
245 0 : errno = err;
246 0 : goto fail;
247 : }
248 4 : TALLOC_FREE(ev);
249 :
250 4 : message_type = CVAL(inbuf, 0);
251 4 : if (message_type != 0x83) {
252 0 : d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
253 : message_type);
254 0 : goto fail;
255 : }
256 :
257 4 : if (smb_len(inbuf) != 1) {
258 0 : d_fprintf(stderr, "Expected smb_len 1, got %d\n",
259 0 : (int)smb_len(inbuf));
260 0 : goto fail;
261 : }
262 :
263 4 : error = CVAL(inbuf, 4);
264 4 : if (error != 0x82) {
265 0 : d_fprintf(stderr, "Expected error 0x82, got %d\n",
266 : (int)error);
267 0 : goto fail;
268 : }
269 :
270 4 : ret = true;
271 4 : fail:
272 4 : TALLOC_FREE(frame);
273 4 : return ret;
274 : }
275 :
276 : /* Insert a NULL at the first separator of the given path and return a pointer
277 : * to the remainder of the string.
278 : */
279 : static char *
280 0 : terminate_path_at_separator(char * path)
281 : {
282 : char * p;
283 :
284 0 : if (!path) {
285 0 : return NULL;
286 : }
287 :
288 0 : if ((p = strchr_m(path, '/'))) {
289 0 : *p = '\0';
290 0 : return p + 1;
291 : }
292 :
293 0 : if ((p = strchr_m(path, '\\'))) {
294 0 : *p = '\0';
295 0 : return p + 1;
296 : }
297 :
298 : /* No separator. */
299 0 : return NULL;
300 : }
301 :
302 : /*
303 : parse a //server/share type UNC name
304 : */
305 0 : bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
306 : char **hostname, char **sharename)
307 : {
308 : char *p;
309 :
310 0 : *hostname = *sharename = NULL;
311 :
312 0 : if (strncmp(unc_name, "\\\\", 2) &&
313 0 : strncmp(unc_name, "//", 2)) {
314 0 : return False;
315 : }
316 :
317 0 : *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
318 0 : p = terminate_path_at_separator(*hostname);
319 :
320 0 : if (p && *p) {
321 0 : *sharename = talloc_strdup(mem_ctx, p);
322 0 : terminate_path_at_separator(*sharename);
323 : }
324 :
325 0 : if (*hostname && *sharename) {
326 0 : return True;
327 : }
328 :
329 0 : TALLOC_FREE(*hostname);
330 0 : TALLOC_FREE(*sharename);
331 0 : return False;
332 : }
333 :
334 492 : static bool torture_open_connection_share(struct cli_state **c,
335 : const char *hostname,
336 : const char *sharename,
337 : int flags)
338 : {
339 : NTSTATUS status;
340 :
341 492 : status = cli_full_connection_creds(c,
342 : myname,
343 : hostname,
344 : NULL, /* dest_ss */
345 : port_to_use,
346 : sharename,
347 : "?????",
348 : torture_creds,
349 : flags);
350 492 : if (!NT_STATUS_IS_OK(status)) {
351 2 : printf("failed to open share connection: //%s/%s port:%d - %s\n",
352 : hostname, sharename, port_to_use, nt_errstr(status));
353 2 : return False;
354 : }
355 :
356 490 : cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
357 :
358 490 : if (do_encrypt) {
359 200 : return force_cli_encryption(*c,
360 : sharename);
361 : }
362 290 : return True;
363 : }
364 :
365 492 : bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
366 : {
367 492 : char **unc_list = NULL;
368 492 : int num_unc_names = 0;
369 : bool result;
370 :
371 492 : if (use_multishare_conn==True) {
372 : char *h, *s;
373 0 : unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
374 0 : if (!unc_list || num_unc_names <= 0) {
375 0 : printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
376 0 : exit(1);
377 : }
378 :
379 0 : if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
380 : NULL, &h, &s)) {
381 0 : printf("Failed to parse UNC name %s\n",
382 0 : unc_list[conn_index % num_unc_names]);
383 0 : TALLOC_FREE(unc_list);
384 0 : exit(1);
385 : }
386 :
387 0 : result = torture_open_connection_share(c, h, s, flags);
388 :
389 : /* h, s were copied earlier */
390 0 : TALLOC_FREE(unc_list);
391 0 : return result;
392 : }
393 :
394 492 : return torture_open_connection_share(c, host, share, flags);
395 : }
396 :
397 484 : bool torture_open_connection(struct cli_state **c, int conn_index)
398 : {
399 484 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
400 :
401 484 : if (use_oplocks) {
402 8 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
403 : }
404 484 : if (use_level_II_oplocks) {
405 8 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
406 : }
407 :
408 484 : return torture_open_connection_flags(c, conn_index, flags);
409 : }
410 :
411 68 : bool torture_init_connection(struct cli_state **pcli)
412 : {
413 : struct cli_state *cli;
414 :
415 68 : cli = open_nbt_connection();
416 68 : if (cli == NULL) {
417 0 : return false;
418 : }
419 :
420 68 : *pcli = cli;
421 68 : return true;
422 : }
423 :
424 5 : bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
425 : {
426 5 : uint16_t old_vuid = cli_state_get_uid(cli);
427 : NTSTATUS status;
428 : bool ret;
429 :
430 5 : cli_state_set_uid(cli, 0);
431 5 : status = cli_session_setup_creds(cli, torture_creds);
432 5 : ret = NT_STATUS_IS_OK(status);
433 5 : *new_vuid = cli_state_get_uid(cli);
434 5 : cli_state_set_uid(cli, old_vuid);
435 5 : return ret;
436 : }
437 :
438 :
439 426 : bool torture_close_connection(struct cli_state *c)
440 : {
441 426 : bool ret = True;
442 : NTSTATUS status;
443 :
444 426 : status = cli_tdis(c);
445 426 : if (!NT_STATUS_IS_OK(status)) {
446 5 : printf("tdis failed (%s)\n", nt_errstr(status));
447 5 : ret = False;
448 : }
449 :
450 426 : cli_shutdown(c);
451 :
452 426 : return ret;
453 : }
454 :
455 48 : void torture_conn_set_sockopt(struct cli_state *cli)
456 : {
457 48 : smbXcli_conn_set_sockopt(cli->conn, sockops);
458 48 : }
459 :
460 : /* check if the server produced the expected dos or nt error code */
461 53 : static bool check_both_error(int line, NTSTATUS status,
462 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
463 : {
464 53 : if (NT_STATUS_IS_DOS(status)) {
465 : uint8_t cclass;
466 : uint32_t num;
467 :
468 : /* Check DOS error */
469 0 : cclass = NT_STATUS_DOS_CLASS(status);
470 0 : num = NT_STATUS_DOS_CODE(status);
471 :
472 0 : if (eclass != cclass || ecode != num) {
473 0 : printf("unexpected error code class=%d code=%d\n",
474 : (int)cclass, (int)num);
475 0 : printf(" expected %d/%d %s (line=%d)\n",
476 : (int)eclass, (int)ecode, nt_errstr(nterr), line);
477 0 : return false;
478 : }
479 : } else {
480 : /* Check NT error */
481 53 : if (!NT_STATUS_EQUAL(nterr, status)) {
482 0 : printf("unexpected error code %s\n",
483 : nt_errstr(status));
484 0 : printf(" expected %s (line=%d)\n",
485 : nt_errstr(nterr), line);
486 0 : return false;
487 : }
488 : }
489 :
490 53 : return true;
491 : }
492 :
493 :
494 : /* check if the server produced the expected error code */
495 38 : static bool check_error(int line, NTSTATUS status,
496 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
497 : {
498 38 : if (NT_STATUS_IS_DOS(status)) {
499 : uint8_t cclass;
500 : uint32_t num;
501 :
502 : /* Check DOS error */
503 :
504 0 : cclass = NT_STATUS_DOS_CLASS(status);
505 0 : num = NT_STATUS_DOS_CODE(status);
506 :
507 0 : if (eclass != cclass || ecode != num) {
508 0 : printf("unexpected error code class=%d code=%d\n",
509 : (int)cclass, (int)num);
510 0 : printf(" expected %d/%d %s (line=%d)\n",
511 : (int)eclass, (int)ecode, nt_errstr(nterr),
512 : line);
513 0 : return False;
514 : }
515 :
516 : } else {
517 : /* Check NT error */
518 :
519 38 : if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
520 1 : printf("unexpected error code %s\n",
521 : nt_errstr(status));
522 1 : printf(" expected %s (line=%d)\n", nt_errstr(nterr),
523 : line);
524 1 : return False;
525 : }
526 : }
527 :
528 37 : return True;
529 : }
530 :
531 :
532 0 : static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
533 : {
534 : NTSTATUS status;
535 :
536 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
537 :
538 0 : while (!NT_STATUS_IS_OK(status)) {
539 0 : if (!check_both_error(__LINE__, status, ERRDOS,
540 0 : ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
541 0 : return false;
542 : }
543 :
544 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
545 : }
546 :
547 0 : return true;
548 : }
549 :
550 :
551 0 : static bool rw_torture(struct cli_state *c)
552 : {
553 0 : const char *lockfname = "\\torture.lck";
554 : fstring fname;
555 : uint16_t fnum;
556 : uint16_t fnum2;
557 0 : pid_t pid2, pid = getpid();
558 : int i, j;
559 : char buf[1024];
560 0 : bool correct = True;
561 0 : size_t nread = 0;
562 : NTSTATUS status;
563 :
564 0 : memset(buf, '\0', sizeof(buf));
565 :
566 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
567 : DENY_NONE, &fnum2);
568 0 : if (!NT_STATUS_IS_OK(status)) {
569 0 : status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
570 : }
571 0 : if (!NT_STATUS_IS_OK(status)) {
572 0 : printf("open of %s failed (%s)\n",
573 : lockfname, nt_errstr(status));
574 0 : return False;
575 : }
576 :
577 0 : for (i=0;i<torture_numops;i++) {
578 0 : unsigned n = (unsigned)sys_random()%10;
579 :
580 0 : if (i % 10 == 0) {
581 0 : printf("%d\r", i); fflush(stdout);
582 : }
583 0 : slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
584 :
585 0 : if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
586 0 : return False;
587 : }
588 :
589 0 : status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
590 : DENY_ALL, &fnum);
591 0 : if (!NT_STATUS_IS_OK(status)) {
592 0 : printf("open failed (%s)\n", nt_errstr(status));
593 0 : correct = False;
594 0 : break;
595 : }
596 :
597 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
598 : sizeof(pid), NULL);
599 0 : if (!NT_STATUS_IS_OK(status)) {
600 0 : printf("write failed (%s)\n", nt_errstr(status));
601 0 : correct = False;
602 : }
603 :
604 0 : for (j=0;j<50;j++) {
605 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
606 0 : sizeof(pid)+(j*sizeof(buf)),
607 : sizeof(buf), NULL);
608 0 : if (!NT_STATUS_IS_OK(status)) {
609 0 : printf("write failed (%s)\n",
610 : nt_errstr(status));
611 0 : correct = False;
612 : }
613 : }
614 :
615 0 : pid2 = 0;
616 :
617 0 : status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
618 : &nread);
619 0 : if (!NT_STATUS_IS_OK(status)) {
620 0 : printf("read failed (%s)\n", nt_errstr(status));
621 0 : correct = false;
622 0 : } else if (nread != sizeof(pid)) {
623 0 : printf("read/write compare failed: "
624 : "recv %ld req %ld\n", (unsigned long)nread,
625 : (unsigned long)sizeof(pid));
626 0 : correct = false;
627 : }
628 :
629 0 : if (pid2 != pid) {
630 0 : printf("data corruption!\n");
631 0 : correct = False;
632 : }
633 :
634 0 : status = cli_close(c, fnum);
635 0 : if (!NT_STATUS_IS_OK(status)) {
636 0 : printf("close failed (%s)\n", nt_errstr(status));
637 0 : correct = False;
638 : }
639 :
640 0 : status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
641 0 : if (!NT_STATUS_IS_OK(status)) {
642 0 : printf("unlink failed (%s)\n", nt_errstr(status));
643 0 : correct = False;
644 : }
645 :
646 0 : status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
647 0 : if (!NT_STATUS_IS_OK(status)) {
648 0 : printf("unlock failed (%s)\n", nt_errstr(status));
649 0 : correct = False;
650 : }
651 : }
652 :
653 0 : cli_close(c, fnum2);
654 0 : cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
655 :
656 0 : printf("%d\n", i);
657 :
658 0 : return correct;
659 : }
660 :
661 0 : static bool run_torture(int dummy)
662 : {
663 : struct cli_state *cli;
664 : bool ret;
665 :
666 0 : cli = current_cli;
667 :
668 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
669 :
670 0 : ret = rw_torture(cli);
671 :
672 0 : if (!torture_close_connection(cli)) {
673 0 : ret = False;
674 : }
675 :
676 0 : return ret;
677 : }
678 :
679 0 : static bool rw_torture3(struct cli_state *c, char *lockfname)
680 : {
681 0 : uint16_t fnum = (uint16_t)-1;
682 0 : unsigned int i = 0;
683 : char buf[131072];
684 : char buf_rd[131072];
685 : unsigned count;
686 0 : unsigned countprev = 0;
687 0 : size_t sent = 0;
688 0 : bool correct = True;
689 0 : NTSTATUS status = NT_STATUS_OK;
690 :
691 0 : srandom(1);
692 0 : for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
693 : {
694 0 : SIVAL(buf, i, sys_random());
695 : }
696 :
697 0 : if (procnum == 0)
698 : {
699 0 : status = cli_unlink(
700 : c, lockfname,
701 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
702 0 : if (!NT_STATUS_IS_OK(status)) {
703 0 : printf("unlink failed (%s) (normal, this file should "
704 : "not exist)\n", nt_errstr(status));
705 : }
706 :
707 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
708 : DENY_NONE, &fnum);
709 0 : if (!NT_STATUS_IS_OK(status)) {
710 0 : printf("first open read/write of %s failed (%s)\n",
711 : lockfname, nt_errstr(status));
712 0 : return False;
713 : }
714 : }
715 : else
716 : {
717 0 : for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
718 : {
719 0 : status = cli_openx(c, lockfname, O_RDONLY,
720 : DENY_NONE, &fnum);
721 0 : if (NT_STATUS_IS_OK(status)) {
722 0 : break;
723 : }
724 0 : smb_msleep(10);
725 : }
726 0 : if (!NT_STATUS_IS_OK(status)) {
727 0 : printf("second open read-only of %s failed (%s)\n",
728 : lockfname, nt_errstr(status));
729 0 : return False;
730 : }
731 : }
732 :
733 0 : i = 0;
734 0 : for (count = 0; count < sizeof(buf); count += sent)
735 : {
736 0 : if (count >= countprev) {
737 0 : printf("%d %8d\r", i, count);
738 0 : fflush(stdout);
739 0 : i++;
740 0 : countprev += (sizeof(buf) / 20);
741 : }
742 :
743 0 : if (procnum == 0)
744 : {
745 0 : sent = ((unsigned)sys_random()%(20))+ 1;
746 0 : if (sent > sizeof(buf) - count)
747 : {
748 0 : sent = sizeof(buf) - count;
749 : }
750 :
751 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
752 : count, sent, NULL);
753 0 : if (!NT_STATUS_IS_OK(status)) {
754 0 : printf("write failed (%s)\n",
755 : nt_errstr(status));
756 0 : correct = False;
757 : }
758 : }
759 : else
760 : {
761 0 : status = cli_read(c, fnum, buf_rd+count, count,
762 : sizeof(buf)-count, &sent);
763 0 : if(!NT_STATUS_IS_OK(status)) {
764 0 : printf("read failed offset:%d size:%ld (%s)\n",
765 : count, (unsigned long)sizeof(buf)-count,
766 : nt_errstr(status));
767 0 : correct = False;
768 0 : sent = 0;
769 0 : } else if (sent > 0) {
770 0 : if (memcmp(buf_rd+count, buf+count, sent) != 0)
771 : {
772 0 : printf("read/write compare failed\n");
773 0 : printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
774 0 : correct = False;
775 0 : break;
776 : }
777 : }
778 : }
779 :
780 : }
781 :
782 0 : status = cli_close(c, fnum);
783 0 : if (!NT_STATUS_IS_OK(status)) {
784 0 : printf("close failed (%s)\n", nt_errstr(status));
785 0 : correct = False;
786 : }
787 :
788 0 : return correct;
789 : }
790 :
791 18 : static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
792 : {
793 18 : const char *lockfname = "\\torture2.lck";
794 : uint16_t fnum1;
795 : uint16_t fnum2;
796 : int i;
797 : char buf[131072];
798 : char buf_rd[131072];
799 18 : bool correct = True;
800 : size_t bytes_read;
801 : NTSTATUS status;
802 :
803 18 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
804 18 : if (!NT_STATUS_IS_OK(status)) {
805 18 : printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
806 : }
807 :
808 18 : status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
809 : DENY_NONE, &fnum1);
810 18 : if (!NT_STATUS_IS_OK(status)) {
811 0 : printf("first open read/write of %s failed (%s)\n",
812 : lockfname, nt_errstr(status));
813 0 : return False;
814 : }
815 :
816 18 : status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
817 18 : if (!NT_STATUS_IS_OK(status)) {
818 0 : printf("second open read-only of %s failed (%s)\n",
819 : lockfname, nt_errstr(status));
820 0 : cli_close(c1, fnum1);
821 0 : return False;
822 : }
823 :
824 1818 : for (i = 0; i < torture_numops; i++)
825 : {
826 1800 : size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
827 1800 : if (i % 10 == 0) {
828 180 : printf("%d\r", i); fflush(stdout);
829 : }
830 :
831 1800 : generate_random_buffer((unsigned char *)buf, buf_size);
832 :
833 1800 : status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
834 : buf_size, NULL);
835 1800 : if (!NT_STATUS_IS_OK(status)) {
836 0 : printf("write failed (%s)\n", nt_errstr(status));
837 0 : correct = False;
838 0 : break;
839 : }
840 :
841 1800 : status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
842 1800 : if(!NT_STATUS_IS_OK(status)) {
843 0 : printf("read failed (%s)\n", nt_errstr(status));
844 0 : correct = false;
845 0 : break;
846 1800 : } else if (bytes_read != buf_size) {
847 0 : printf("read failed\n");
848 0 : printf("read %ld, expected %ld\n",
849 : (unsigned long)bytes_read,
850 : (unsigned long)buf_size);
851 0 : correct = False;
852 0 : break;
853 : }
854 :
855 1800 : if (memcmp(buf_rd, buf, buf_size) != 0)
856 : {
857 0 : printf("read/write compare failed\n");
858 0 : correct = False;
859 0 : break;
860 : }
861 : }
862 :
863 18 : status = cli_close(c2, fnum2);
864 18 : if (!NT_STATUS_IS_OK(status)) {
865 0 : printf("close failed (%s)\n", nt_errstr(status));
866 0 : correct = False;
867 : }
868 :
869 18 : status = cli_close(c1, fnum1);
870 18 : if (!NT_STATUS_IS_OK(status)) {
871 0 : printf("close failed (%s)\n", nt_errstr(status));
872 0 : correct = False;
873 : }
874 :
875 18 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
876 18 : if (!NT_STATUS_IS_OK(status)) {
877 0 : printf("unlink failed (%s)\n", nt_errstr(status));
878 0 : correct = False;
879 : }
880 :
881 18 : return correct;
882 : }
883 :
884 9 : static bool run_readwritetest(int dummy)
885 : {
886 : struct cli_state *cli1, *cli2;
887 9 : bool test1, test2 = False;
888 :
889 9 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
890 0 : return False;
891 : }
892 9 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
893 9 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
894 :
895 9 : printf("starting readwritetest\n");
896 :
897 9 : test1 = rw_torture2(cli1, cli2);
898 9 : printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
899 :
900 9 : if (test1) {
901 9 : test2 = rw_torture2(cli1, cli1);
902 9 : printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
903 : }
904 :
905 9 : if (!torture_close_connection(cli1)) {
906 0 : test1 = False;
907 : }
908 :
909 9 : if (!torture_close_connection(cli2)) {
910 0 : test2 = False;
911 : }
912 :
913 9 : return (test1 && test2);
914 : }
915 :
916 0 : static bool run_readwritemulti(int dummy)
917 : {
918 : struct cli_state *cli;
919 : bool test;
920 :
921 0 : cli = current_cli;
922 :
923 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
924 :
925 0 : printf("run_readwritemulti: fname %s\n", randomfname);
926 0 : test = rw_torture3(cli, randomfname);
927 :
928 0 : if (!torture_close_connection(cli)) {
929 0 : test = False;
930 : }
931 :
932 0 : return test;
933 : }
934 :
935 14 : static bool run_readwritelarge_internal(void)
936 : {
937 : static struct cli_state *cli1;
938 : uint16_t fnum1;
939 14 : const char *lockfname = "\\large.dat";
940 : off_t fsize;
941 : char buf[126*1024];
942 14 : bool correct = True;
943 : NTSTATUS status;
944 :
945 14 : if (!torture_open_connection(&cli1, 0)) {
946 0 : return False;
947 : }
948 14 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
949 14 : memset(buf,'\0',sizeof(buf));
950 :
951 14 : printf("starting readwritelarge_internal\n");
952 :
953 14 : cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
954 :
955 14 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
956 : DENY_NONE, &fnum1);
957 14 : if (!NT_STATUS_IS_OK(status)) {
958 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
959 0 : return False;
960 : }
961 :
962 14 : cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
963 :
964 14 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
965 : NULL, NULL, NULL);
966 14 : if (!NT_STATUS_IS_OK(status)) {
967 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
968 0 : correct = False;
969 : }
970 :
971 14 : if (fsize == sizeof(buf))
972 14 : printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
973 : (unsigned long)fsize);
974 : else {
975 0 : printf("readwritelarge_internal test 1 failed (size = %lx)\n",
976 : (unsigned long)fsize);
977 0 : correct = False;
978 : }
979 :
980 14 : status = cli_close(cli1, fnum1);
981 14 : if (!NT_STATUS_IS_OK(status)) {
982 0 : printf("close failed (%s)\n", nt_errstr(status));
983 0 : correct = False;
984 : }
985 :
986 14 : status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
987 14 : if (!NT_STATUS_IS_OK(status)) {
988 0 : printf("unlink failed (%s)\n", nt_errstr(status));
989 0 : correct = False;
990 : }
991 :
992 14 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
993 : DENY_NONE, &fnum1);
994 14 : if (!NT_STATUS_IS_OK(status)) {
995 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
996 0 : return False;
997 : }
998 :
999 14 : cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1000 :
1001 14 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1002 : NULL, NULL, NULL);
1003 14 : if (!NT_STATUS_IS_OK(status)) {
1004 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
1005 0 : correct = False;
1006 : }
1007 :
1008 14 : if (fsize == sizeof(buf))
1009 14 : printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1010 : (unsigned long)fsize);
1011 : else {
1012 0 : printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1013 : (unsigned long)fsize);
1014 0 : correct = False;
1015 : }
1016 :
1017 14 : status = cli_close(cli1, fnum1);
1018 14 : if (!NT_STATUS_IS_OK(status)) {
1019 0 : printf("close failed (%s)\n", nt_errstr(status));
1020 0 : correct = False;
1021 : }
1022 :
1023 14 : if (!torture_close_connection(cli1)) {
1024 0 : correct = False;
1025 : }
1026 14 : return correct;
1027 : }
1028 :
1029 9 : static bool run_readwritelarge(int dummy)
1030 : {
1031 9 : return run_readwritelarge_internal();
1032 : }
1033 :
1034 5 : static bool run_readwritelarge_signtest(int dummy)
1035 : {
1036 : bool ret;
1037 5 : signing_state = SMB_SIGNING_REQUIRED;
1038 5 : ret = run_readwritelarge_internal();
1039 5 : signing_state = SMB_SIGNING_DEFAULT;
1040 5 : return ret;
1041 : }
1042 :
1043 : int line_count = 0;
1044 : int nbio_id;
1045 :
1046 : #define ival(s) strtol(s, NULL, 0)
1047 :
1048 : /* run a test that simulates an approximate netbench client load */
1049 0 : static bool run_netbench(int client)
1050 : {
1051 : struct cli_state *cli;
1052 : int i;
1053 : char line[1024];
1054 : char cname[20];
1055 : FILE *f;
1056 : const char *params[20];
1057 0 : bool correct = True;
1058 :
1059 0 : cli = current_cli;
1060 :
1061 0 : nbio_id = client;
1062 :
1063 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1064 :
1065 0 : nb_setup(cli);
1066 :
1067 0 : slprintf(cname,sizeof(cname)-1, "client%d", client);
1068 :
1069 0 : f = fopen(client_txt, "r");
1070 :
1071 0 : if (!f) {
1072 0 : perror(client_txt);
1073 0 : return False;
1074 : }
1075 :
1076 0 : while (fgets(line, sizeof(line)-1, f)) {
1077 : char *saveptr;
1078 0 : line_count++;
1079 :
1080 0 : line[strlen(line)-1] = 0;
1081 :
1082 : /* printf("[%d] %s\n", line_count, line); */
1083 :
1084 0 : all_string_sub(line,"client1", cname, sizeof(line));
1085 :
1086 : /* parse the command parameters */
1087 0 : params[0] = strtok_r(line, " ", &saveptr);
1088 0 : i = 0;
1089 0 : while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1090 :
1091 0 : params[i] = "";
1092 :
1093 0 : if (i < 2) continue;
1094 :
1095 0 : if (!strncmp(params[0],"SMB", 3)) {
1096 0 : printf("ERROR: You are using a dbench 1 load file\n");
1097 0 : exit(1);
1098 : }
1099 :
1100 0 : if (!strcmp(params[0],"NTCreateX")) {
1101 0 : nb_createx(params[1], ival(params[2]), ival(params[3]),
1102 0 : ival(params[4]));
1103 0 : } else if (!strcmp(params[0],"Close")) {
1104 0 : nb_close(ival(params[1]));
1105 0 : } else if (!strcmp(params[0],"Rename")) {
1106 0 : nb_rename(params[1], params[2]);
1107 0 : } else if (!strcmp(params[0],"Unlink")) {
1108 0 : nb_unlink(params[1]);
1109 0 : } else if (!strcmp(params[0],"Deltree")) {
1110 0 : nb_deltree(params[1]);
1111 0 : } else if (!strcmp(params[0],"Rmdir")) {
1112 0 : nb_rmdir(params[1]);
1113 0 : } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1114 0 : nb_qpathinfo(params[1]);
1115 0 : } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1116 0 : nb_qfileinfo(ival(params[1]));
1117 0 : } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1118 0 : nb_qfsinfo(ival(params[1]));
1119 0 : } else if (!strcmp(params[0],"FIND_FIRST")) {
1120 0 : nb_findfirst(params[1]);
1121 0 : } else if (!strcmp(params[0],"WriteX")) {
1122 0 : nb_writex(ival(params[1]),
1123 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1124 0 : } else if (!strcmp(params[0],"ReadX")) {
1125 0 : nb_readx(ival(params[1]),
1126 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1127 0 : } else if (!strcmp(params[0],"Flush")) {
1128 0 : nb_flush(ival(params[1]));
1129 : } else {
1130 0 : printf("Unknown operation %s\n", params[0]);
1131 0 : exit(1);
1132 : }
1133 : }
1134 0 : fclose(f);
1135 :
1136 0 : nb_cleanup();
1137 :
1138 0 : if (!torture_close_connection(cli)) {
1139 0 : correct = False;
1140 : }
1141 :
1142 0 : return correct;
1143 : }
1144 :
1145 :
1146 : /* run a test that simulates an approximate netbench client load */
1147 0 : static bool run_nbench(int dummy)
1148 : {
1149 : double t;
1150 0 : bool correct = True;
1151 :
1152 0 : nbio_shmem(torture_nprocs);
1153 :
1154 0 : nbio_id = -1;
1155 :
1156 0 : signal(SIGALRM, nb_alarm);
1157 0 : alarm(1);
1158 0 : t = create_procs(run_netbench, &correct);
1159 0 : alarm(0);
1160 :
1161 0 : printf("\nThroughput %g MB/sec\n",
1162 0 : 1.0e-6 * nbio_total() / t);
1163 0 : return correct;
1164 : }
1165 :
1166 :
1167 : /*
1168 : This test checks for two things:
1169 :
1170 : 1) correct support for retaining locks over a close (ie. the server
1171 : must not use posix semantics)
1172 : 2) support for lock timeouts
1173 : */
1174 5 : static bool run_locktest1(int dummy)
1175 : {
1176 : struct cli_state *cli1, *cli2;
1177 5 : const char *fname = "\\lockt1.lck";
1178 : uint16_t fnum1, fnum2, fnum3;
1179 : time_t t1, t2;
1180 : unsigned lock_timeout;
1181 : NTSTATUS status;
1182 :
1183 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1184 0 : return False;
1185 : }
1186 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1187 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1188 :
1189 5 : printf("starting locktest1\n");
1190 :
1191 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1192 :
1193 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1194 : &fnum1);
1195 5 : if (!NT_STATUS_IS_OK(status)) {
1196 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1197 0 : return False;
1198 : }
1199 :
1200 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1201 5 : if (!NT_STATUS_IS_OK(status)) {
1202 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1203 0 : return False;
1204 : }
1205 :
1206 5 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1207 5 : if (!NT_STATUS_IS_OK(status)) {
1208 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1209 0 : return False;
1210 : }
1211 :
1212 5 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1213 5 : if (!NT_STATUS_IS_OK(status)) {
1214 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1215 0 : return false;
1216 : }
1217 :
1218 5 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1219 5 : if (NT_STATUS_IS_OK(status)) {
1220 0 : printf("lock2 succeeded! This is a locking bug\n");
1221 0 : return false;
1222 : } else {
1223 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1224 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1225 0 : return false;
1226 : }
1227 : }
1228 :
1229 5 : lock_timeout = (1 + (random() % 20));
1230 5 : printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1231 5 : t1 = time(NULL);
1232 5 : status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1233 5 : if (NT_STATUS_IS_OK(status)) {
1234 0 : printf("lock3 succeeded! This is a locking bug\n");
1235 0 : return false;
1236 : } else {
1237 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1238 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1239 0 : return false;
1240 : }
1241 : }
1242 5 : t2 = time(NULL);
1243 :
1244 5 : if (ABS(t2 - t1) < lock_timeout-1) {
1245 0 : printf("error: This server appears not to support timed lock requests\n");
1246 : }
1247 :
1248 5 : printf("server slept for %u seconds for a %u second timeout\n",
1249 : (unsigned int)(t2-t1), lock_timeout);
1250 :
1251 5 : status = cli_close(cli1, fnum2);
1252 5 : if (!NT_STATUS_IS_OK(status)) {
1253 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1254 0 : return False;
1255 : }
1256 :
1257 5 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1258 5 : if (NT_STATUS_IS_OK(status)) {
1259 0 : printf("lock4 succeeded! This is a locking bug\n");
1260 0 : return false;
1261 : } else {
1262 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1263 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1264 0 : return false;
1265 : }
1266 : }
1267 :
1268 5 : status = cli_close(cli1, fnum1);
1269 5 : if (!NT_STATUS_IS_OK(status)) {
1270 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1271 0 : return False;
1272 : }
1273 :
1274 5 : status = cli_close(cli2, fnum3);
1275 5 : if (!NT_STATUS_IS_OK(status)) {
1276 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1277 0 : return False;
1278 : }
1279 :
1280 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1281 5 : if (!NT_STATUS_IS_OK(status)) {
1282 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1283 0 : return False;
1284 : }
1285 :
1286 :
1287 5 : if (!torture_close_connection(cli1)) {
1288 0 : return False;
1289 : }
1290 :
1291 5 : if (!torture_close_connection(cli2)) {
1292 0 : return False;
1293 : }
1294 :
1295 5 : printf("Passed locktest1\n");
1296 5 : return True;
1297 : }
1298 :
1299 : /*
1300 : this checks to see if a secondary tconx can use open files from an
1301 : earlier tconx
1302 : */
1303 5 : static bool run_tcon_test(int dummy)
1304 : {
1305 : static struct cli_state *cli;
1306 5 : const char *fname = "\\tcontest.tmp";
1307 : uint16_t fnum1;
1308 : uint32_t cnum1, cnum2, cnum3;
1309 5 : struct smbXcli_tcon *orig_tcon = NULL;
1310 : uint16_t vuid1, vuid2;
1311 : char buf[4];
1312 5 : bool ret = True;
1313 : NTSTATUS status;
1314 :
1315 5 : memset(buf, '\0', sizeof(buf));
1316 :
1317 5 : if (!torture_open_connection(&cli, 0)) {
1318 0 : return False;
1319 : }
1320 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1321 :
1322 5 : printf("starting tcontest\n");
1323 :
1324 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1325 :
1326 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1327 5 : if (!NT_STATUS_IS_OK(status)) {
1328 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1329 0 : return False;
1330 : }
1331 :
1332 5 : cnum1 = cli_state_get_tid(cli);
1333 5 : vuid1 = cli_state_get_uid(cli);
1334 :
1335 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1336 5 : if (!NT_STATUS_IS_OK(status)) {
1337 0 : printf("initial write failed (%s)", nt_errstr(status));
1338 0 : return False;
1339 : }
1340 :
1341 5 : orig_tcon = cli_state_save_tcon(cli);
1342 5 : if (orig_tcon == NULL) {
1343 0 : return false;
1344 : }
1345 :
1346 5 : status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1347 5 : if (!NT_STATUS_IS_OK(status)) {
1348 0 : printf("%s refused 2nd tree connect (%s)\n", host,
1349 : nt_errstr(status));
1350 0 : cli_state_restore_tcon(cli, orig_tcon);
1351 0 : cli_shutdown(cli);
1352 0 : return False;
1353 : }
1354 :
1355 5 : cnum2 = cli_state_get_tid(cli);
1356 5 : cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1357 5 : vuid2 = cli_state_get_uid(cli) + 1;
1358 :
1359 : /* try a write with the wrong tid */
1360 5 : cli_state_set_tid(cli, cnum2);
1361 :
1362 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1363 5 : if (NT_STATUS_IS_OK(status)) {
1364 0 : printf("* server allows write with wrong TID\n");
1365 0 : ret = False;
1366 : } else {
1367 5 : printf("server fails write with wrong TID : %s\n",
1368 : nt_errstr(status));
1369 : }
1370 :
1371 :
1372 : /* try a write with an invalid tid */
1373 5 : cli_state_set_tid(cli, cnum3);
1374 :
1375 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1376 5 : if (NT_STATUS_IS_OK(status)) {
1377 0 : printf("* server allows write with invalid TID\n");
1378 0 : ret = False;
1379 : } else {
1380 5 : printf("server fails write with invalid TID : %s\n",
1381 : nt_errstr(status));
1382 : }
1383 :
1384 : /* try a write with an invalid vuid */
1385 5 : cli_state_set_uid(cli, vuid2);
1386 5 : cli_state_set_tid(cli, cnum1);
1387 :
1388 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1389 5 : if (NT_STATUS_IS_OK(status)) {
1390 0 : printf("* server allows write with invalid VUID\n");
1391 0 : ret = False;
1392 : } else {
1393 5 : printf("server fails write with invalid VUID : %s\n",
1394 : nt_errstr(status));
1395 : }
1396 :
1397 5 : cli_state_set_tid(cli, cnum1);
1398 5 : cli_state_set_uid(cli, vuid1);
1399 :
1400 5 : status = cli_close(cli, fnum1);
1401 5 : if (!NT_STATUS_IS_OK(status)) {
1402 0 : printf("close failed (%s)\n", nt_errstr(status));
1403 0 : cli_state_restore_tcon(cli, orig_tcon);
1404 0 : cli_shutdown(cli);
1405 0 : return False;
1406 : }
1407 :
1408 5 : cli_state_set_tid(cli, cnum2);
1409 :
1410 5 : status = cli_tdis(cli);
1411 5 : if (!NT_STATUS_IS_OK(status)) {
1412 0 : printf("secondary tdis failed (%s)\n", nt_errstr(status));
1413 0 : cli_state_restore_tcon(cli, orig_tcon);
1414 0 : cli_shutdown(cli);
1415 0 : return False;
1416 : }
1417 :
1418 5 : cli_state_restore_tcon(cli, orig_tcon);
1419 :
1420 5 : cli_state_set_tid(cli, cnum1);
1421 :
1422 5 : if (!torture_close_connection(cli)) {
1423 0 : return False;
1424 : }
1425 :
1426 5 : return ret;
1427 : }
1428 :
1429 :
1430 : /*
1431 : checks for old style tcon support
1432 : */
1433 5 : static bool run_tcon2_test(int dummy)
1434 : {
1435 : static struct cli_state *cli;
1436 : uint16_t cnum, max_xmit;
1437 : char *service;
1438 : NTSTATUS status;
1439 :
1440 5 : if (!torture_open_connection(&cli, 0)) {
1441 0 : return False;
1442 : }
1443 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1444 :
1445 5 : printf("starting tcon2 test\n");
1446 :
1447 5 : if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1448 0 : return false;
1449 : }
1450 :
1451 5 : status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1452 :
1453 5 : SAFE_FREE(service);
1454 :
1455 5 : if (!NT_STATUS_IS_OK(status)) {
1456 5 : printf("tcon2 failed : %s\n", nt_errstr(status));
1457 : } else {
1458 0 : printf("tcon OK : max_xmit=%d cnum=%d\n",
1459 : (int)max_xmit, (int)cnum);
1460 : }
1461 :
1462 5 : if (!torture_close_connection(cli)) {
1463 0 : return False;
1464 : }
1465 :
1466 5 : printf("Passed tcon2 test\n");
1467 5 : return True;
1468 : }
1469 :
1470 50 : static bool tcon_devtest(struct cli_state *cli,
1471 : const char *myshare, const char *devtype,
1472 : const char *return_devtype,
1473 : NTSTATUS expected_error)
1474 : {
1475 : NTSTATUS status;
1476 : bool ret;
1477 :
1478 50 : status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1479 :
1480 50 : if (NT_STATUS_IS_OK(expected_error)) {
1481 20 : if (NT_STATUS_IS_OK(status)) {
1482 40 : if (return_devtype != NULL &&
1483 20 : strequal(cli->dev, return_devtype)) {
1484 20 : ret = True;
1485 : } else {
1486 0 : printf("tconX to share %s with type %s "
1487 : "succeeded but returned the wrong "
1488 : "device type (got [%s] but should have got [%s])\n",
1489 : myshare, devtype, cli->dev, return_devtype);
1490 0 : ret = False;
1491 : }
1492 : } else {
1493 0 : printf("tconX to share %s with type %s "
1494 : "should have succeeded but failed\n",
1495 : myshare, devtype);
1496 0 : ret = False;
1497 : }
1498 20 : cli_tdis(cli);
1499 : } else {
1500 30 : if (NT_STATUS_IS_OK(status)) {
1501 0 : printf("tconx to share %s with type %s "
1502 : "should have failed but succeeded\n",
1503 : myshare, devtype);
1504 0 : ret = False;
1505 : } else {
1506 30 : if (NT_STATUS_EQUAL(status, expected_error)) {
1507 30 : ret = True;
1508 : } else {
1509 0 : printf("Returned unexpected error\n");
1510 0 : ret = False;
1511 : }
1512 : }
1513 : }
1514 50 : return ret;
1515 : }
1516 :
1517 : /*
1518 : checks for correct tconX support
1519 : */
1520 5 : static bool run_tcon_devtype_test(int dummy)
1521 : {
1522 : static struct cli_state *cli1 = NULL;
1523 5 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1524 : NTSTATUS status;
1525 5 : bool ret = True;
1526 :
1527 5 : status = cli_full_connection_creds(&cli1,
1528 : myname,
1529 : host,
1530 : NULL, /* dest_ss */
1531 : port_to_use,
1532 : NULL, /* service */
1533 : NULL, /* service_type */
1534 : torture_creds,
1535 : flags);
1536 :
1537 5 : if (!NT_STATUS_IS_OK(status)) {
1538 0 : printf("could not open connection\n");
1539 0 : return False;
1540 : }
1541 :
1542 5 : if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1543 0 : ret = False;
1544 :
1545 5 : if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1546 0 : ret = False;
1547 :
1548 5 : if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1549 0 : ret = False;
1550 :
1551 5 : if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1552 0 : ret = False;
1553 :
1554 5 : if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1555 0 : ret = False;
1556 :
1557 5 : if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1558 0 : ret = False;
1559 :
1560 5 : if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1561 0 : ret = False;
1562 :
1563 5 : if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1564 0 : ret = False;
1565 :
1566 5 : if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1567 0 : ret = False;
1568 :
1569 5 : if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1570 0 : ret = False;
1571 :
1572 5 : cli_shutdown(cli1);
1573 :
1574 5 : if (ret)
1575 5 : printf("Passed tcondevtest\n");
1576 :
1577 5 : return ret;
1578 : }
1579 :
1580 :
1581 : /*
1582 : This test checks that
1583 :
1584 : 1) the server supports multiple locking contexts on the one SMB
1585 : connection, distinguished by PID.
1586 :
1587 : 2) the server correctly fails overlapping locks made by the same PID (this
1588 : goes against POSIX behaviour, which is why it is tricky to implement)
1589 :
1590 : 3) the server denies unlock requests by an incorrect client PID
1591 : */
1592 5 : static bool run_locktest2(int dummy)
1593 : {
1594 : static struct cli_state *cli;
1595 5 : const char *fname = "\\lockt2.lck";
1596 : uint16_t fnum1, fnum2, fnum3;
1597 5 : bool correct = True;
1598 : NTSTATUS status;
1599 :
1600 5 : if (!torture_open_connection(&cli, 0)) {
1601 0 : return False;
1602 : }
1603 :
1604 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1605 :
1606 5 : printf("starting locktest2\n");
1607 :
1608 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1609 :
1610 5 : cli_setpid(cli, 1);
1611 :
1612 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1613 5 : if (!NT_STATUS_IS_OK(status)) {
1614 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1615 0 : return False;
1616 : }
1617 :
1618 5 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1619 5 : if (!NT_STATUS_IS_OK(status)) {
1620 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1621 0 : return False;
1622 : }
1623 :
1624 5 : cli_setpid(cli, 2);
1625 :
1626 5 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1627 5 : if (!NT_STATUS_IS_OK(status)) {
1628 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1629 0 : return False;
1630 : }
1631 :
1632 5 : cli_setpid(cli, 1);
1633 :
1634 5 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1635 5 : if (!NT_STATUS_IS_OK(status)) {
1636 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1637 0 : return false;
1638 : }
1639 :
1640 5 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1641 5 : if (NT_STATUS_IS_OK(status)) {
1642 0 : printf("WRITE lock1 succeeded! This is a locking bug\n");
1643 0 : correct = false;
1644 : } else {
1645 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1646 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1647 0 : return false;
1648 : }
1649 : }
1650 :
1651 5 : status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1652 5 : if (NT_STATUS_IS_OK(status)) {
1653 0 : printf("WRITE lock2 succeeded! This is a locking bug\n");
1654 0 : correct = false;
1655 : } else {
1656 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1657 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1658 0 : return false;
1659 : }
1660 : }
1661 :
1662 5 : status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1663 5 : if (NT_STATUS_IS_OK(status)) {
1664 0 : printf("READ lock2 succeeded! This is a locking bug\n");
1665 0 : correct = false;
1666 : } else {
1667 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1668 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1669 0 : return false;
1670 : }
1671 : }
1672 :
1673 5 : status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1674 5 : if (!NT_STATUS_IS_OK(status)) {
1675 0 : printf("lock at 100 failed (%s)\n", nt_errstr(status));
1676 : }
1677 5 : cli_setpid(cli, 2);
1678 5 : if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1679 0 : printf("unlock at 100 succeeded! This is a locking bug\n");
1680 0 : correct = False;
1681 : }
1682 :
1683 5 : status = cli_unlock(cli, fnum1, 0, 4);
1684 5 : if (NT_STATUS_IS_OK(status)) {
1685 0 : printf("unlock1 succeeded! This is a locking bug\n");
1686 0 : correct = false;
1687 : } else {
1688 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1689 5 : NT_STATUS_RANGE_NOT_LOCKED)) {
1690 0 : return false;
1691 : }
1692 : }
1693 :
1694 5 : status = cli_unlock(cli, fnum1, 0, 8);
1695 5 : if (NT_STATUS_IS_OK(status)) {
1696 0 : printf("unlock2 succeeded! This is a locking bug\n");
1697 0 : correct = false;
1698 : } else {
1699 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1700 5 : NT_STATUS_RANGE_NOT_LOCKED)) {
1701 0 : return false;
1702 : }
1703 : }
1704 :
1705 5 : status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1706 5 : if (NT_STATUS_IS_OK(status)) {
1707 0 : printf("lock3 succeeded! This is a locking bug\n");
1708 0 : correct = false;
1709 : } else {
1710 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1711 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1712 0 : return false;
1713 : }
1714 : }
1715 :
1716 5 : cli_setpid(cli, 1);
1717 :
1718 5 : status = cli_close(cli, fnum1);
1719 5 : if (!NT_STATUS_IS_OK(status)) {
1720 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1721 0 : return False;
1722 : }
1723 :
1724 5 : status = cli_close(cli, fnum2);
1725 5 : if (!NT_STATUS_IS_OK(status)) {
1726 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1727 0 : return False;
1728 : }
1729 :
1730 5 : status = cli_close(cli, fnum3);
1731 5 : if (!NT_STATUS_IS_OK(status)) {
1732 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1733 0 : return False;
1734 : }
1735 :
1736 5 : if (!torture_close_connection(cli)) {
1737 0 : correct = False;
1738 : }
1739 :
1740 5 : printf("locktest2 finished\n");
1741 :
1742 5 : return correct;
1743 : }
1744 :
1745 :
1746 : /*
1747 : This test checks that
1748 :
1749 : 1) the server supports the full offset range in lock requests
1750 : */
1751 5 : static bool run_locktest3(int dummy)
1752 : {
1753 : static struct cli_state *cli1, *cli2;
1754 5 : const char *fname = "\\lockt3.lck";
1755 : uint16_t fnum1, fnum2;
1756 : int i;
1757 : uint32_t offset;
1758 5 : bool correct = True;
1759 : NTSTATUS status;
1760 :
1761 : #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1762 :
1763 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1764 0 : return False;
1765 : }
1766 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1767 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1768 :
1769 5 : printf("starting locktest3\n");
1770 :
1771 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1772 :
1773 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1774 : &fnum1);
1775 5 : if (!NT_STATUS_IS_OK(status)) {
1776 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1777 0 : return False;
1778 : }
1779 :
1780 5 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1781 5 : if (!NT_STATUS_IS_OK(status)) {
1782 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1783 0 : return False;
1784 : }
1785 :
1786 505 : for (offset=i=0;i<torture_numops;i++) {
1787 500 : NEXT_OFFSET;
1788 :
1789 500 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1790 500 : if (!NT_STATUS_IS_OK(status)) {
1791 0 : printf("lock1 %d failed (%s)\n",
1792 : i,
1793 : nt_errstr(status));
1794 0 : return False;
1795 : }
1796 :
1797 500 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1798 500 : if (!NT_STATUS_IS_OK(status)) {
1799 0 : printf("lock2 %d failed (%s)\n",
1800 : i,
1801 : nt_errstr(status));
1802 0 : return False;
1803 : }
1804 : }
1805 :
1806 505 : for (offset=i=0;i<torture_numops;i++) {
1807 500 : NEXT_OFFSET;
1808 :
1809 500 : status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1810 500 : if (NT_STATUS_IS_OK(status)) {
1811 0 : printf("error: lock1 %d succeeded!\n", i);
1812 0 : return False;
1813 : }
1814 :
1815 500 : status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1816 500 : if (NT_STATUS_IS_OK(status)) {
1817 0 : printf("error: lock2 %d succeeded!\n", i);
1818 0 : return False;
1819 : }
1820 :
1821 500 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1822 500 : if (NT_STATUS_IS_OK(status)) {
1823 0 : printf("error: lock3 %d succeeded!\n", i);
1824 0 : return False;
1825 : }
1826 :
1827 500 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1828 500 : if (NT_STATUS_IS_OK(status)) {
1829 0 : printf("error: lock4 %d succeeded!\n", i);
1830 0 : return False;
1831 : }
1832 : }
1833 :
1834 505 : for (offset=i=0;i<torture_numops;i++) {
1835 500 : NEXT_OFFSET;
1836 :
1837 500 : status = cli_unlock(cli1, fnum1, offset-1, 1);
1838 500 : if (!NT_STATUS_IS_OK(status)) {
1839 0 : printf("unlock1 %d failed (%s)\n",
1840 : i,
1841 : nt_errstr(status));
1842 0 : return False;
1843 : }
1844 :
1845 500 : status = cli_unlock(cli2, fnum2, offset-2, 1);
1846 500 : if (!NT_STATUS_IS_OK(status)) {
1847 0 : printf("unlock2 %d failed (%s)\n",
1848 : i,
1849 : nt_errstr(status));
1850 0 : return False;
1851 : }
1852 : }
1853 :
1854 5 : status = cli_close(cli1, fnum1);
1855 5 : if (!NT_STATUS_IS_OK(status)) {
1856 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1857 0 : return False;
1858 : }
1859 :
1860 5 : status = cli_close(cli2, fnum2);
1861 5 : if (!NT_STATUS_IS_OK(status)) {
1862 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1863 0 : return False;
1864 : }
1865 :
1866 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1867 5 : if (!NT_STATUS_IS_OK(status)) {
1868 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1869 0 : return False;
1870 : }
1871 :
1872 5 : if (!torture_close_connection(cli1)) {
1873 0 : correct = False;
1874 : }
1875 :
1876 5 : if (!torture_close_connection(cli2)) {
1877 0 : correct = False;
1878 : }
1879 :
1880 5 : printf("finished locktest3\n");
1881 :
1882 5 : return correct;
1883 : }
1884 :
1885 40 : static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1886 : char *buf, off_t offset, size_t size,
1887 : size_t *nread, size_t expect)
1888 : {
1889 : NTSTATUS status;
1890 : size_t l_nread;
1891 :
1892 40 : status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1893 :
1894 40 : if(!NT_STATUS_IS_OK(status)) {
1895 20 : return false;
1896 20 : } else if (l_nread != expect) {
1897 0 : return false;
1898 : }
1899 :
1900 20 : if (nread) {
1901 0 : *nread = l_nread;
1902 : }
1903 :
1904 20 : return true;
1905 : }
1906 :
1907 : #define EXPECTED(ret, v) if ((ret) != (v)) { \
1908 : printf("** "); correct = False; \
1909 : }
1910 :
1911 : /*
1912 : looks at overlapping locks
1913 : */
1914 5 : static bool run_locktest4(int dummy)
1915 : {
1916 : static struct cli_state *cli1, *cli2;
1917 5 : const char *fname = "\\lockt4.lck";
1918 : uint16_t fnum1, fnum2, f;
1919 : bool ret;
1920 : char buf[1000];
1921 5 : bool correct = True;
1922 : NTSTATUS status;
1923 :
1924 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1925 0 : return False;
1926 : }
1927 :
1928 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1929 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1930 :
1931 5 : printf("starting locktest4\n");
1932 :
1933 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1934 :
1935 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1936 5 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1937 :
1938 5 : memset(buf, 0, sizeof(buf));
1939 :
1940 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1941 : NULL);
1942 5 : if (!NT_STATUS_IS_OK(status)) {
1943 0 : printf("Failed to create file: %s\n", nt_errstr(status));
1944 0 : correct = False;
1945 0 : goto fail;
1946 : }
1947 :
1948 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1949 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1950 5 : EXPECTED(ret, False);
1951 5 : printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1952 :
1953 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1954 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1955 5 : EXPECTED(ret, True);
1956 5 : printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1957 :
1958 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1959 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1960 5 : EXPECTED(ret, False);
1961 5 : printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1962 :
1963 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1964 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1965 5 : EXPECTED(ret, True);
1966 5 : printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1967 :
1968 10 : ret = (cli_setpid(cli1, 1),
1969 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1970 5 : (cli_setpid(cli1, 2),
1971 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1972 5 : EXPECTED(ret, False);
1973 5 : printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1974 :
1975 10 : ret = (cli_setpid(cli1, 1),
1976 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1977 5 : (cli_setpid(cli1, 2),
1978 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1979 5 : EXPECTED(ret, True);
1980 5 : printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1981 :
1982 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1983 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1984 5 : EXPECTED(ret, True);
1985 5 : printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1986 :
1987 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1988 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1989 5 : EXPECTED(ret, False);
1990 5 : printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1991 :
1992 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1993 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1994 5 : EXPECTED(ret, False);
1995 5 : printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1996 :
1997 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1998 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1999 5 : EXPECTED(ret, True);
2000 5 : printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2001 :
2002 10 : ret = (cli_setpid(cli1, 1),
2003 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2004 5 : (cli_setpid(cli1, 2),
2005 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2006 5 : EXPECTED(ret, False);
2007 5 : printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2008 :
2009 15 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2010 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2011 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2012 5 : EXPECTED(ret, False);
2013 5 : printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2014 :
2015 :
2016 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2017 5 : test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2018 5 : EXPECTED(ret, False);
2019 5 : printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2020 :
2021 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2022 5 : ret = NT_STATUS_IS_OK(status);
2023 5 : if (ret) {
2024 5 : status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2025 : NULL);
2026 5 : ret = NT_STATUS_IS_OK(status);
2027 : }
2028 5 : EXPECTED(ret, False);
2029 5 : printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2030 :
2031 :
2032 15 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2033 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2034 15 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2035 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2036 5 : EXPECTED(ret, True);
2037 5 : printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2038 :
2039 :
2040 15 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2041 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2042 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2043 10 : test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2044 5 : !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2045 10 : 150, 4, NULL))) &&
2046 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2047 5 : EXPECTED(ret, True);
2048 5 : printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2049 :
2050 15 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2051 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2052 5 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2053 10 : 160, 4, NULL)) &&
2054 5 : test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2055 5 : EXPECTED(ret, True);
2056 5 : printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2057 :
2058 15 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2059 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2060 5 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2061 10 : 170, 4, NULL)) &&
2062 5 : test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2063 5 : EXPECTED(ret, True);
2064 5 : printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2065 :
2066 15 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2067 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2068 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2069 5 : !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2070 10 : 190, 4, NULL)) &&
2071 5 : test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2072 5 : EXPECTED(ret, True);
2073 5 : printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2074 :
2075 5 : cli_close(cli1, fnum1);
2076 5 : cli_close(cli2, fnum2);
2077 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2078 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2079 15 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2080 10 : NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2081 10 : NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2082 15 : NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2083 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2084 5 : cli_close(cli1, f);
2085 5 : cli_close(cli1, fnum1);
2086 5 : EXPECTED(ret, True);
2087 5 : printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2088 :
2089 5 : fail:
2090 5 : cli_close(cli1, fnum1);
2091 5 : cli_close(cli2, fnum2);
2092 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2093 5 : torture_close_connection(cli1);
2094 5 : torture_close_connection(cli2);
2095 :
2096 5 : printf("finished locktest4\n");
2097 5 : return correct;
2098 : }
2099 :
2100 : /*
2101 : looks at lock upgrade/downgrade.
2102 : */
2103 5 : static bool run_locktest5(int dummy)
2104 : {
2105 : static struct cli_state *cli1, *cli2;
2106 5 : const char *fname = "\\lockt5.lck";
2107 : uint16_t fnum1, fnum2, fnum3;
2108 : bool ret;
2109 : char buf[1000];
2110 5 : bool correct = True;
2111 : NTSTATUS status;
2112 :
2113 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2114 0 : return False;
2115 : }
2116 :
2117 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2118 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2119 :
2120 5 : printf("starting locktest5\n");
2121 :
2122 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2123 :
2124 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2125 5 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2126 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2127 :
2128 5 : memset(buf, 0, sizeof(buf));
2129 :
2130 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2131 : NULL);
2132 5 : if (!NT_STATUS_IS_OK(status)) {
2133 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2134 0 : correct = False;
2135 0 : goto fail;
2136 : }
2137 :
2138 : /* Check for NT bug... */
2139 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2140 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2141 5 : cli_close(cli1, fnum1);
2142 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2143 5 : status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2144 5 : ret = NT_STATUS_IS_OK(status);
2145 5 : EXPECTED(ret, True);
2146 5 : printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2147 5 : cli_close(cli1, fnum1);
2148 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2149 5 : cli_unlock(cli1, fnum3, 0, 1);
2150 :
2151 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2152 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2153 5 : EXPECTED(ret, True);
2154 5 : printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2155 :
2156 5 : status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2157 5 : ret = NT_STATUS_IS_OK(status);
2158 5 : EXPECTED(ret, False);
2159 :
2160 5 : printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2161 :
2162 : /* Unlock the process 2 lock. */
2163 5 : cli_unlock(cli2, fnum2, 0, 4);
2164 :
2165 5 : status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2166 5 : ret = NT_STATUS_IS_OK(status);
2167 5 : EXPECTED(ret, False);
2168 :
2169 5 : printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2170 :
2171 : /* Unlock the process 1 fnum3 lock. */
2172 5 : cli_unlock(cli1, fnum3, 0, 4);
2173 :
2174 : /* Stack 2 more locks here. */
2175 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2176 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2177 :
2178 5 : EXPECTED(ret, True);
2179 5 : printf("the same process %s stack read locks\n", ret?"can":"cannot");
2180 :
2181 : /* Unlock the first process lock, then check this was the WRITE lock that was
2182 : removed. */
2183 :
2184 10 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2185 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2186 :
2187 5 : EXPECTED(ret, True);
2188 5 : printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2189 :
2190 : /* Unlock the process 2 lock. */
2191 5 : cli_unlock(cli2, fnum2, 0, 4);
2192 :
2193 : /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2194 :
2195 15 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2196 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2197 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2198 :
2199 5 : EXPECTED(ret, True);
2200 5 : printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2201 :
2202 : /* Ensure the next unlock fails. */
2203 5 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2204 5 : EXPECTED(ret, False);
2205 5 : printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2206 :
2207 : /* Ensure connection 2 can get a write lock. */
2208 5 : status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2209 5 : ret = NT_STATUS_IS_OK(status);
2210 5 : EXPECTED(ret, True);
2211 :
2212 5 : printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2213 :
2214 :
2215 5 : fail:
2216 5 : cli_close(cli1, fnum1);
2217 5 : cli_close(cli2, fnum2);
2218 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2219 5 : if (!torture_close_connection(cli1)) {
2220 0 : correct = False;
2221 : }
2222 5 : if (!torture_close_connection(cli2)) {
2223 0 : correct = False;
2224 : }
2225 :
2226 5 : printf("finished locktest5\n");
2227 :
2228 5 : return correct;
2229 : }
2230 :
2231 : /*
2232 : tries the unusual lockingX locktype bits
2233 : */
2234 5 : static bool run_locktest6(int dummy)
2235 : {
2236 : static struct cli_state *cli;
2237 5 : const char *fname[1] = { "\\lock6.txt" };
2238 : int i;
2239 : uint16_t fnum;
2240 : NTSTATUS status;
2241 :
2242 5 : if (!torture_open_connection(&cli, 0)) {
2243 0 : return False;
2244 : }
2245 :
2246 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
2247 :
2248 5 : printf("starting locktest6\n");
2249 :
2250 10 : for (i=0;i<1;i++) {
2251 5 : printf("Testing %s\n", fname[i]);
2252 :
2253 5 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2254 :
2255 5 : cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2256 5 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2257 5 : cli_close(cli, fnum);
2258 5 : printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2259 :
2260 5 : cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2261 5 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2262 5 : cli_close(cli, fnum);
2263 5 : printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2264 :
2265 5 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2266 : }
2267 :
2268 5 : torture_close_connection(cli);
2269 :
2270 5 : printf("finished locktest6\n");
2271 5 : return True;
2272 : }
2273 :
2274 5 : static bool run_locktest7(int dummy)
2275 : {
2276 : struct cli_state *cli1;
2277 5 : const char *fname = "\\lockt7.lck";
2278 : uint16_t fnum1;
2279 : char buf[200];
2280 5 : bool correct = False;
2281 : size_t nread;
2282 : NTSTATUS status;
2283 :
2284 5 : if (!torture_open_connection(&cli1, 0)) {
2285 0 : return False;
2286 : }
2287 :
2288 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2289 :
2290 5 : printf("starting locktest7\n");
2291 :
2292 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2293 :
2294 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2295 :
2296 5 : memset(buf, 0, sizeof(buf));
2297 :
2298 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2299 : NULL);
2300 5 : if (!NT_STATUS_IS_OK(status)) {
2301 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2302 0 : goto fail;
2303 : }
2304 :
2305 5 : cli_setpid(cli1, 1);
2306 :
2307 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2308 5 : if (!NT_STATUS_IS_OK(status)) {
2309 0 : printf("Unable to apply read lock on range 130:4, "
2310 : "error was %s\n", nt_errstr(status));
2311 0 : goto fail;
2312 : } else {
2313 5 : printf("pid1 successfully locked range 130:4 for READ\n");
2314 : }
2315 :
2316 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2317 5 : if (!NT_STATUS_IS_OK(status)) {
2318 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2319 : nt_errstr(status));
2320 0 : goto fail;
2321 5 : } else if (nread != 4) {
2322 0 : printf("pid1 unable to read the range 130:4, "
2323 : "recv %ld req %d\n", (unsigned long)nread, 4);
2324 0 : goto fail;
2325 : } else {
2326 5 : printf("pid1 successfully read the range 130:4\n");
2327 : }
2328 :
2329 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2330 5 : if (!NT_STATUS_IS_OK(status)) {
2331 5 : printf("pid1 unable to write to the range 130:4, error was "
2332 : "%s\n", nt_errstr(status));
2333 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2334 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2335 0 : goto fail;
2336 : }
2337 : } else {
2338 0 : printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2339 0 : goto fail;
2340 : }
2341 :
2342 5 : cli_setpid(cli1, 2);
2343 :
2344 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2345 5 : if (!NT_STATUS_IS_OK(status)) {
2346 0 : printf("pid2 unable to read the range 130:4, error was %s\n",
2347 : nt_errstr(status));
2348 0 : goto fail;
2349 5 : } else if (nread != 4) {
2350 0 : printf("pid2 unable to read the range 130:4, "
2351 : "recv %ld req %d\n", (unsigned long)nread, 4);
2352 0 : goto fail;
2353 : } else {
2354 5 : printf("pid2 successfully read the range 130:4\n");
2355 : }
2356 :
2357 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2358 5 : if (!NT_STATUS_IS_OK(status)) {
2359 5 : printf("pid2 unable to write to the range 130:4, error was "
2360 : "%s\n", nt_errstr(status));
2361 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2362 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2363 0 : goto fail;
2364 : }
2365 : } else {
2366 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2367 0 : goto fail;
2368 : }
2369 :
2370 5 : cli_setpid(cli1, 1);
2371 5 : cli_unlock(cli1, fnum1, 130, 4);
2372 :
2373 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2374 5 : if (!NT_STATUS_IS_OK(status)) {
2375 0 : printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2376 0 : goto fail;
2377 : } else {
2378 5 : printf("pid1 successfully locked range 130:4 for WRITE\n");
2379 : }
2380 :
2381 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2382 5 : if (!NT_STATUS_IS_OK(status)) {
2383 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2384 : nt_errstr(status));
2385 0 : goto fail;
2386 5 : } else if (nread != 4) {
2387 0 : printf("pid1 unable to read the range 130:4, "
2388 : "recv %ld req %d\n", (unsigned long)nread, 4);
2389 0 : goto fail;
2390 : } else {
2391 5 : printf("pid1 successfully read the range 130:4\n");
2392 : }
2393 :
2394 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2395 5 : if (!NT_STATUS_IS_OK(status)) {
2396 0 : printf("pid1 unable to write to the range 130:4, error was "
2397 : "%s\n", nt_errstr(status));
2398 0 : goto fail;
2399 : } else {
2400 5 : printf("pid1 successfully wrote to the range 130:4\n");
2401 : }
2402 :
2403 5 : cli_setpid(cli1, 2);
2404 :
2405 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2406 5 : if (!NT_STATUS_IS_OK(status)) {
2407 5 : printf("pid2 unable to read the range 130:4, error was "
2408 : "%s\n", nt_errstr(status));
2409 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2410 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2411 0 : goto fail;
2412 : }
2413 : } else {
2414 0 : printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2415 : (unsigned long)nread);
2416 0 : goto fail;
2417 : }
2418 :
2419 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2420 5 : if (!NT_STATUS_IS_OK(status)) {
2421 5 : printf("pid2 unable to write to the range 130:4, error was "
2422 : "%s\n", nt_errstr(status));
2423 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2424 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2425 0 : goto fail;
2426 : }
2427 : } else {
2428 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2429 0 : goto fail;
2430 : }
2431 :
2432 5 : cli_unlock(cli1, fnum1, 130, 0);
2433 5 : correct = True;
2434 :
2435 5 : fail:
2436 5 : cli_close(cli1, fnum1);
2437 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2438 5 : torture_close_connection(cli1);
2439 :
2440 5 : printf("finished locktest7\n");
2441 5 : return correct;
2442 : }
2443 :
2444 : /*
2445 : * This demonstrates a problem with our use of GPFS share modes: A file
2446 : * descriptor sitting in the pending close queue holding a GPFS share mode
2447 : * blocks opening a file another time. Happens with Word 2007 temp files.
2448 : * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2449 : * open is denied with NT_STATUS_SHARING_VIOLATION.
2450 : */
2451 :
2452 0 : static bool run_locktest8(int dummy)
2453 : {
2454 : struct cli_state *cli1;
2455 0 : const char *fname = "\\lockt8.lck";
2456 : uint16_t fnum1, fnum2;
2457 : char buf[200];
2458 0 : bool correct = False;
2459 : NTSTATUS status;
2460 :
2461 0 : if (!torture_open_connection(&cli1, 0)) {
2462 0 : return False;
2463 : }
2464 :
2465 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2466 :
2467 0 : printf("starting locktest8\n");
2468 :
2469 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2470 :
2471 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2472 : &fnum1);
2473 0 : if (!NT_STATUS_IS_OK(status)) {
2474 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2475 0 : return false;
2476 : }
2477 :
2478 0 : memset(buf, 0, sizeof(buf));
2479 :
2480 0 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2481 0 : if (!NT_STATUS_IS_OK(status)) {
2482 0 : d_fprintf(stderr, "cli_openx second time returned %s\n",
2483 : nt_errstr(status));
2484 0 : goto fail;
2485 : }
2486 :
2487 0 : status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2488 0 : if (!NT_STATUS_IS_OK(status)) {
2489 0 : printf("Unable to apply read lock on range 1:1, error was "
2490 : "%s\n", nt_errstr(status));
2491 0 : goto fail;
2492 : }
2493 :
2494 0 : status = cli_close(cli1, fnum1);
2495 0 : if (!NT_STATUS_IS_OK(status)) {
2496 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2497 0 : goto fail;
2498 : }
2499 :
2500 0 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2501 0 : if (!NT_STATUS_IS_OK(status)) {
2502 0 : d_fprintf(stderr, "cli_openx third time returned %s\n",
2503 : nt_errstr(status));
2504 0 : goto fail;
2505 : }
2506 :
2507 0 : correct = true;
2508 :
2509 0 : fail:
2510 0 : cli_close(cli1, fnum1);
2511 0 : cli_close(cli1, fnum2);
2512 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2513 0 : torture_close_connection(cli1);
2514 :
2515 0 : printf("finished locktest8\n");
2516 0 : return correct;
2517 : }
2518 :
2519 : /*
2520 : * This test is designed to be run in conjunction with
2521 : * external NFS or POSIX locks taken in the filesystem.
2522 : * It checks that the smbd server will block until the
2523 : * lock is released and then acquire it. JRA.
2524 : */
2525 :
2526 : static bool got_alarm;
2527 : static struct cli_state *alarm_cli;
2528 :
2529 0 : static void alarm_handler(int dummy)
2530 : {
2531 0 : got_alarm = True;
2532 0 : }
2533 :
2534 0 : static void alarm_handler_parent(int dummy)
2535 : {
2536 0 : smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2537 0 : }
2538 :
2539 8 : static void do_local_lock(const char *fname, int read_fd, int write_fd)
2540 : {
2541 : int fd;
2542 8 : char c = '\0';
2543 : struct flock lock;
2544 8 : const char *local_pathname = NULL;
2545 : int ret;
2546 :
2547 8 : local_pathname = talloc_asprintf(talloc_tos(),
2548 : "%s/%s", local_path, fname);
2549 8 : if (!local_pathname) {
2550 0 : printf("child: alloc fail\n");
2551 0 : exit(1);
2552 : }
2553 :
2554 8 : unlink(local_pathname);
2555 8 : fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2556 8 : if (fd == -1) {
2557 0 : printf("child: open of %s failed %s.\n",
2558 0 : local_pathname, strerror(errno));
2559 0 : exit(1);
2560 : }
2561 :
2562 : /* Now take a fcntl lock. */
2563 8 : lock.l_type = F_WRLCK;
2564 8 : lock.l_whence = SEEK_SET;
2565 8 : lock.l_start = 0;
2566 8 : lock.l_len = 4;
2567 8 : lock.l_pid = getpid();
2568 :
2569 8 : ret = fcntl(fd,F_SETLK,&lock);
2570 8 : if (ret == -1) {
2571 0 : printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2572 0 : local_pathname, strerror(errno));
2573 0 : exit(1);
2574 : } else {
2575 8 : printf("child: got lock 0:4 on file %s.\n",
2576 : local_pathname );
2577 8 : fflush(stdout);
2578 : }
2579 :
2580 8 : CatchSignal(SIGALRM, alarm_handler);
2581 8 : alarm(5);
2582 : /* Signal the parent. */
2583 8 : if (write(write_fd, &c, 1) != 1) {
2584 0 : printf("child: start signal fail %s.\n",
2585 0 : strerror(errno));
2586 0 : exit(1);
2587 : }
2588 8 : alarm(0);
2589 :
2590 8 : alarm(10);
2591 : /* Wait for the parent to be ready. */
2592 8 : if (read(read_fd, &c, 1) != 1) {
2593 0 : printf("child: reply signal fail %s.\n",
2594 0 : strerror(errno));
2595 0 : exit(1);
2596 : }
2597 8 : alarm(0);
2598 :
2599 8 : sleep(5);
2600 8 : close(fd);
2601 8 : printf("child: released lock 0:4 on file %s.\n",
2602 : local_pathname );
2603 8 : fflush(stdout);
2604 8 : exit(0);
2605 : }
2606 :
2607 8 : static bool _run_locktest9X(const char *fname, int timeout)
2608 : {
2609 : struct cli_state *cli1;
2610 8 : char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2611 : uint16_t fnum;
2612 8 : bool correct = False;
2613 : int pipe_in[2], pipe_out[2];
2614 : pid_t child_pid;
2615 8 : char c = '\0';
2616 : int ret;
2617 : struct timeval start;
2618 : double seconds;
2619 : NTSTATUS status;
2620 :
2621 8 : printf("starting locktest9X: %s\n", fname);
2622 :
2623 8 : if (local_path == NULL) {
2624 0 : d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2625 0 : return false;
2626 : }
2627 :
2628 8 : if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2629 0 : return false;
2630 : }
2631 :
2632 8 : child_pid = fork();
2633 16 : if (child_pid == -1) {
2634 0 : return false;
2635 : }
2636 :
2637 16 : if (child_pid == 0) {
2638 : /* Child. */
2639 8 : do_local_lock(fname, pipe_out[0], pipe_in[1]);
2640 0 : exit(0);
2641 : }
2642 :
2643 8 : close(pipe_out[0]);
2644 8 : close(pipe_in[1]);
2645 8 : pipe_out[0] = -1;
2646 8 : pipe_in[1] = -1;
2647 :
2648 : /* Parent. */
2649 8 : ret = read(pipe_in[0], &c, 1);
2650 8 : if (ret != 1) {
2651 0 : d_fprintf(stderr, "failed to read start signal from child. %s\n",
2652 0 : strerror(errno));
2653 0 : return false;
2654 : }
2655 :
2656 8 : if (!torture_open_connection(&cli1, 0)) {
2657 0 : return false;
2658 : }
2659 :
2660 8 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2661 :
2662 8 : status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2663 : &fnum);
2664 8 : if (!NT_STATUS_IS_OK(status)) {
2665 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2666 0 : return false;
2667 : }
2668 :
2669 : /* Ensure the child has the lock. */
2670 8 : status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2671 8 : if (NT_STATUS_IS_OK(status)) {
2672 0 : d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2673 0 : goto fail;
2674 : } else {
2675 8 : d_printf("Child has the lock.\n");
2676 : }
2677 :
2678 : /* Tell the child to wait 5 seconds then exit. */
2679 8 : ret = write(pipe_out[1], &c, 1);
2680 8 : if (ret != 1) {
2681 0 : d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2682 0 : strerror(errno));
2683 0 : goto fail;
2684 : }
2685 :
2686 : /* Wait 20 seconds for the lock. */
2687 8 : alarm_cli = cli1;
2688 8 : CatchSignal(SIGALRM, alarm_handler_parent);
2689 8 : alarm(20);
2690 :
2691 8 : start = timeval_current();
2692 :
2693 8 : status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2694 8 : if (!NT_STATUS_IS_OK(status)) {
2695 0 : d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2696 : "%s\n", nt_errstr(status));
2697 0 : goto fail_nofd;
2698 : }
2699 8 : alarm(0);
2700 :
2701 8 : seconds = timeval_elapsed(&start);
2702 :
2703 8 : printf("Parent got the lock after %.2f seconds.\n",
2704 : seconds);
2705 :
2706 8 : status = cli_close(cli1, fnum);
2707 8 : if (!NT_STATUS_IS_OK(status)) {
2708 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2709 0 : goto fail;
2710 : }
2711 :
2712 8 : correct = true;
2713 :
2714 8 : fail:
2715 8 : cli_close(cli1, fnum);
2716 8 : torture_close_connection(cli1);
2717 :
2718 8 : fail_nofd:
2719 :
2720 8 : printf("finished locktest9X: %s\n", fname);
2721 8 : return correct;
2722 : }
2723 :
2724 4 : static bool run_locktest9a(int dummy)
2725 : {
2726 4 : return _run_locktest9X("lock9a.dat", -1);
2727 : }
2728 :
2729 4 : static bool run_locktest9b(int dummy)
2730 : {
2731 4 : return _run_locktest9X("lock9b.dat", 10000);
2732 : }
2733 :
2734 : struct locktest10_state {
2735 : bool ok;
2736 : bool done;
2737 : };
2738 :
2739 : static void locktest10_lockingx_done(struct tevent_req *subreq);
2740 : static void locktest10_read_andx_done(struct tevent_req *subreq);
2741 :
2742 5 : static bool run_locktest10(int dummy)
2743 : {
2744 5 : struct tevent_context *ev = NULL;
2745 5 : struct cli_state *cli1 = NULL;
2746 5 : struct cli_state *cli2 = NULL;
2747 5 : struct smb1_lock_element lck = { 0 };
2748 5 : struct tevent_req *reqs[2] = { NULL };
2749 5 : struct tevent_req *smbreqs[2] = { NULL };
2750 5 : const char fname[] = "\\lockt10.lck";
2751 : uint16_t fnum1, fnum2;
2752 5 : bool ret = false;
2753 : bool ok;
2754 5 : uint8_t data = 1;
2755 5 : struct locktest10_state state = { .ok = true };
2756 : NTSTATUS status;
2757 :
2758 5 : printf("starting locktest10\n");
2759 :
2760 5 : ev = samba_tevent_context_init(NULL);
2761 5 : if (ev == NULL) {
2762 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
2763 0 : goto done;
2764 : }
2765 :
2766 5 : ok = torture_open_connection(&cli1, 0);
2767 5 : if (!ok) {
2768 0 : goto done;
2769 : }
2770 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2771 :
2772 5 : ok = torture_open_connection(&cli2, 1);
2773 5 : if (!ok) {
2774 0 : goto done;
2775 : }
2776 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2777 :
2778 5 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2779 5 : if (!NT_STATUS_IS_OK(status)) {
2780 0 : d_fprintf(stderr,
2781 : "cli_openx failed: %s\n",
2782 : nt_errstr(status));
2783 0 : goto done;
2784 : }
2785 :
2786 5 : status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2787 5 : if (!NT_STATUS_IS_OK(status)) {
2788 0 : d_fprintf(stderr,
2789 : "cli_writeall failed: %s\n",
2790 : nt_errstr(status));
2791 0 : goto done;
2792 : }
2793 :
2794 5 : status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2795 5 : if (!NT_STATUS_IS_OK(status)) {
2796 0 : d_fprintf(stderr,
2797 : "cli_openx failed: %s\n",
2798 : nt_errstr(status));
2799 0 : goto done;
2800 : }
2801 :
2802 5 : status = cli_locktype(
2803 : cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2804 5 : if (!NT_STATUS_IS_OK(status)) {
2805 0 : d_fprintf(stderr,
2806 : "cli_locktype failed: %s\n",
2807 : nt_errstr(status));
2808 0 : goto done;
2809 : }
2810 :
2811 5 : lck = (struct smb1_lock_element) {
2812 5 : .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2813 : };
2814 :
2815 5 : reqs[0] = cli_lockingx_create(
2816 : ev, /* mem_ctx */
2817 : ev, /* tevent_context */
2818 : cli1, /* cli */
2819 : fnum1, /* fnum */
2820 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2821 : 0, /* newoplocklevel */
2822 : 1, /* timeout */
2823 : 0, /* num_unlocks */
2824 : NULL, /* unlocks */
2825 : 1, /* num_locks */
2826 : &lck, /* locks */
2827 : &smbreqs[0]); /* psmbreq */
2828 5 : if (reqs[0] == NULL) {
2829 0 : d_fprintf(stderr, "cli_lockingx_create failed\n");
2830 0 : goto done;
2831 : }
2832 5 : tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2833 :
2834 5 : reqs[1] = cli_read_andx_create(
2835 : ev, /* mem_ctx */
2836 : ev, /* ev */
2837 : cli1, /* cli */
2838 : fnum1, /* fnum */
2839 : 0, /* offset */
2840 : 1, /* size */
2841 : &smbreqs[1]); /* psmbreq */
2842 5 : if (reqs[1] == NULL) {
2843 0 : d_fprintf(stderr, "cli_read_andx_create failed\n");
2844 0 : goto done;
2845 : }
2846 5 : tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2847 :
2848 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2849 5 : if (!NT_STATUS_IS_OK(status)) {
2850 0 : d_fprintf(stderr,
2851 : "smb1cli_req_chain_submit failed: %s\n",
2852 : nt_errstr(status));
2853 0 : goto done;
2854 : }
2855 :
2856 35 : while (!state.done) {
2857 25 : tevent_loop_once(ev);
2858 : }
2859 :
2860 5 : torture_close_connection(cli1);
2861 :
2862 5 : if (state.ok) {
2863 5 : ret = true;
2864 : }
2865 5 : done:
2866 5 : return ret;
2867 : }
2868 :
2869 5 : static void locktest10_lockingx_done(struct tevent_req *subreq)
2870 : {
2871 5 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2872 : NTSTATUS status;
2873 :
2874 5 : status = cli_lockingx_recv(subreq);
2875 5 : TALLOC_FREE(subreq);
2876 :
2877 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2878 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
2879 0 : state->ok = false;
2880 : }
2881 5 : }
2882 :
2883 5 : static void locktest10_read_andx_done(struct tevent_req *subreq)
2884 : {
2885 5 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2886 5 : ssize_t received = -1;
2887 5 : uint8_t *rcvbuf = NULL;
2888 : NTSTATUS status;
2889 :
2890 5 : status = cli_read_andx_recv(subreq, &received, &rcvbuf);
2891 :
2892 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
2893 0 : d_printf("cli_read_andx returned %s\n", nt_errstr(status));
2894 0 : state->ok = false;
2895 : }
2896 :
2897 5 : state->done = true;
2898 5 : TALLOC_FREE(subreq);
2899 5 : }
2900 :
2901 5 : static bool run_locktest11(int dummy)
2902 : {
2903 : struct cli_state *cli1;
2904 5 : const char *fname = "\\lockt11.lck";
2905 : NTSTATUS status;
2906 : uint16_t fnum;
2907 5 : bool ret = false;
2908 :
2909 5 : if (!torture_open_connection(&cli1, 0)) {
2910 0 : return false;
2911 : }
2912 :
2913 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2914 :
2915 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2916 :
2917 5 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
2918 5 : if (!NT_STATUS_IS_OK(status)) {
2919 0 : d_fprintf(stderr,
2920 : "cli_openx returned %s\n",
2921 : nt_errstr(status));
2922 0 : return false;
2923 : }
2924 :
2925 : /*
2926 : * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
2927 : * returns NT_STATUS_OK
2928 : */
2929 :
2930 5 : status = cli_lockingx(
2931 : cli1, /* cli */
2932 : fnum, /* fnum */
2933 : LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
2934 : 0, /* newoplocklevel */
2935 : 0, /* timeout */
2936 : 0, /* num_unlocks */
2937 : NULL, /* unlocks */
2938 : 0, /* num_locks */
2939 : NULL); /* locks */
2940 :
2941 5 : if (!NT_STATUS_IS_OK(status)) {
2942 1 : d_printf("cli_lockingX returned %s\n", nt_errstr(status));
2943 1 : goto fail;
2944 : }
2945 :
2946 4 : ret = true;
2947 5 : fail:
2948 5 : cli_close(cli1, fnum);
2949 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2950 :
2951 5 : return ret;
2952 : }
2953 :
2954 : struct deferred_close_state {
2955 : struct tevent_context *ev;
2956 : struct cli_state *cli;
2957 : uint16_t fnum;
2958 : };
2959 :
2960 : static void deferred_close_waited(struct tevent_req *subreq);
2961 : static void deferred_close_done(struct tevent_req *subreq);
2962 :
2963 5 : static struct tevent_req *deferred_close_send(
2964 : TALLOC_CTX *mem_ctx,
2965 : struct tevent_context *ev,
2966 : int wait_secs,
2967 : struct cli_state *cli,
2968 : uint16_t fnum)
2969 : {
2970 5 : struct tevent_req *req = NULL, *subreq = NULL;
2971 5 : struct deferred_close_state *state = NULL;
2972 5 : struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
2973 :
2974 5 : req = tevent_req_create(
2975 : mem_ctx, &state, struct deferred_close_state);
2976 5 : if (req == NULL) {
2977 0 : return NULL;
2978 : }
2979 5 : state->ev = ev;
2980 5 : state->cli = cli;
2981 5 : state->fnum = fnum;
2982 :
2983 5 : subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
2984 5 : if (tevent_req_nomem(subreq, req)) {
2985 0 : return tevent_req_post(req, ev);
2986 : }
2987 5 : tevent_req_set_callback(subreq, deferred_close_waited, req);
2988 5 : return req;
2989 : }
2990 :
2991 5 : static void deferred_close_waited(struct tevent_req *subreq)
2992 : {
2993 5 : struct tevent_req *req = tevent_req_callback_data(
2994 : subreq, struct tevent_req);
2995 5 : struct deferred_close_state *state = tevent_req_data(
2996 : req, struct deferred_close_state);
2997 : bool ok;
2998 :
2999 5 : ok = tevent_wakeup_recv(subreq);
3000 5 : TALLOC_FREE(subreq);
3001 5 : if (!ok) {
3002 0 : tevent_req_oom(req);
3003 0 : return;
3004 : }
3005 :
3006 5 : subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3007 5 : if (tevent_req_nomem(subreq, req)) {
3008 0 : return;
3009 : }
3010 5 : tevent_req_set_callback(subreq, deferred_close_done, req);
3011 : }
3012 :
3013 5 : static void deferred_close_done(struct tevent_req *subreq)
3014 : {
3015 5 : NTSTATUS status = cli_close_recv(subreq);
3016 5 : tevent_req_simple_finish_ntstatus(subreq, status);
3017 5 : }
3018 :
3019 5 : static NTSTATUS deferred_close_recv(struct tevent_req *req)
3020 : {
3021 5 : return tevent_req_simple_recv_ntstatus(req);
3022 : }
3023 :
3024 : struct lockread_state {
3025 : struct smb1_lock_element lck;
3026 : struct tevent_req *reqs[2];
3027 : struct tevent_req *smbreqs[2];
3028 : NTSTATUS lock_status;
3029 : NTSTATUS read_status;
3030 : uint8_t *readbuf;
3031 : };
3032 :
3033 : static void lockread_lockingx_done(struct tevent_req *subreq);
3034 : static void lockread_read_andx_done(struct tevent_req *subreq);
3035 :
3036 5 : static struct tevent_req *lockread_send(
3037 : TALLOC_CTX *mem_ctx,
3038 : struct tevent_context *ev,
3039 : struct cli_state *cli,
3040 : uint16_t fnum)
3041 : {
3042 5 : struct tevent_req *req = NULL;
3043 5 : struct lockread_state *state = NULL;
3044 : NTSTATUS status;
3045 :
3046 5 : req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3047 5 : if (req == NULL) {
3048 0 : return NULL;
3049 : }
3050 :
3051 10 : state->lck = (struct smb1_lock_element) {
3052 5 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3053 : };
3054 :
3055 10 : state->reqs[0] = cli_lockingx_create(
3056 : ev, /* mem_ctx */
3057 : ev, /* tevent_context */
3058 : cli, /* cli */
3059 : fnum, /* fnum */
3060 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3061 : 0, /* newoplocklevel */
3062 : 10000, /* timeout */
3063 : 0, /* num_unlocks */
3064 : NULL, /* unlocks */
3065 : 1, /* num_locks */
3066 5 : &state->lck, /* locks */
3067 5 : &state->smbreqs[0]); /* psmbreq */
3068 5 : if (tevent_req_nomem(state->reqs[0], req)) {
3069 0 : return tevent_req_post(req, ev);
3070 : }
3071 5 : tevent_req_set_callback(
3072 5 : state->reqs[0], lockread_lockingx_done, req);
3073 :
3074 5 : state->reqs[1] = cli_read_andx_create(
3075 : ev, /* mem_ctx */
3076 : ev, /* ev */
3077 : cli, /* cli */
3078 : fnum, /* fnum */
3079 : 0, /* offset */
3080 : 1, /* size */
3081 5 : &state->smbreqs[1]); /* psmbreq */
3082 5 : if (tevent_req_nomem(state->reqs[1], req)) {
3083 0 : return tevent_req_post(req, ev);
3084 : }
3085 5 : tevent_req_set_callback(
3086 5 : state->reqs[1], lockread_read_andx_done, req);
3087 :
3088 5 : status = smb1cli_req_chain_submit(state->smbreqs, 2);
3089 5 : if (tevent_req_nterror(req, status)) {
3090 0 : return tevent_req_post(req, ev);
3091 : }
3092 5 : return req;
3093 : }
3094 :
3095 5 : static void lockread_lockingx_done(struct tevent_req *subreq)
3096 : {
3097 5 : struct tevent_req *req = tevent_req_callback_data(
3098 : subreq, struct tevent_req);
3099 5 : struct lockread_state *state = tevent_req_data(
3100 : req, struct lockread_state);
3101 5 : state->lock_status = cli_lockingx_recv(subreq);
3102 5 : TALLOC_FREE(subreq);
3103 5 : d_fprintf(stderr,
3104 : "lockingx returned %s\n",
3105 : nt_errstr(state->lock_status));
3106 5 : }
3107 :
3108 5 : static void lockread_read_andx_done(struct tevent_req *subreq)
3109 : {
3110 5 : struct tevent_req *req = tevent_req_callback_data(
3111 : subreq, struct tevent_req);
3112 5 : struct lockread_state *state = tevent_req_data(
3113 : req, struct lockread_state);
3114 5 : ssize_t received = -1;
3115 5 : uint8_t *rcvbuf = NULL;
3116 :
3117 5 : state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3118 :
3119 5 : d_fprintf(stderr,
3120 : "read returned %s\n",
3121 : nt_errstr(state->read_status));
3122 :
3123 5 : if (!NT_STATUS_IS_OK(state->read_status)) {
3124 4 : TALLOC_FREE(subreq);
3125 4 : tevent_req_done(req);
3126 4 : return;
3127 : }
3128 :
3129 1 : if (received > 0) {
3130 1 : state->readbuf = talloc_memdup(state, rcvbuf, received);
3131 1 : TALLOC_FREE(subreq);
3132 1 : if (tevent_req_nomem(state->readbuf, req)) {
3133 0 : return;
3134 : }
3135 : }
3136 1 : TALLOC_FREE(subreq);
3137 1 : tevent_req_done(req);
3138 : }
3139 :
3140 5 : static NTSTATUS lockread_recv(
3141 : struct tevent_req *req,
3142 : NTSTATUS *lock_status,
3143 : NTSTATUS *read_status,
3144 : TALLOC_CTX *mem_ctx,
3145 : uint8_t **read_buf)
3146 : {
3147 5 : struct lockread_state *state = tevent_req_data(
3148 : req, struct lockread_state);
3149 : NTSTATUS status;
3150 :
3151 5 : if (tevent_req_is_nterror(req, &status)) {
3152 0 : return status;
3153 : }
3154 :
3155 5 : *lock_status = state->lock_status;
3156 5 : *read_status = state->read_status;
3157 5 : if (state->readbuf != NULL) {
3158 1 : *read_buf = talloc_move(mem_ctx, &state->readbuf);
3159 : } else {
3160 4 : *read_buf = NULL;
3161 : }
3162 :
3163 5 : return NT_STATUS_OK;
3164 : }
3165 :
3166 : struct lock12_state {
3167 : uint8_t dummy;
3168 : };
3169 :
3170 : static void lock12_closed(struct tevent_req *subreq);
3171 : static void lock12_read(struct tevent_req *subreq);
3172 :
3173 5 : static struct tevent_req *lock12_send(
3174 : TALLOC_CTX *mem_ctx,
3175 : struct tevent_context *ev,
3176 : struct cli_state *cli,
3177 : uint16_t fnum1,
3178 : uint16_t fnum2)
3179 : {
3180 5 : struct tevent_req *req = NULL, *subreq = NULL;
3181 5 : struct lock12_state *state = NULL;
3182 :
3183 5 : req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3184 5 : if (req == NULL) {
3185 0 : return NULL;
3186 : }
3187 :
3188 5 : subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3189 5 : if (tevent_req_nomem(subreq, req)) {
3190 0 : return tevent_req_post(req, ev);
3191 : }
3192 5 : tevent_req_set_callback(subreq, lock12_closed, req);
3193 :
3194 5 : subreq = lockread_send(state, ev, cli, fnum2);
3195 5 : if (tevent_req_nomem(subreq, req)) {
3196 0 : return tevent_req_post(req, ev);
3197 : }
3198 5 : tevent_req_set_callback(subreq, lock12_read, req);
3199 :
3200 5 : return req;
3201 : }
3202 :
3203 5 : static void lock12_closed(struct tevent_req *subreq)
3204 : {
3205 5 : struct tevent_req *req = tevent_req_callback_data(
3206 : subreq, struct tevent_req);
3207 : NTSTATUS status;
3208 :
3209 5 : status = deferred_close_recv(subreq);
3210 5 : TALLOC_FREE(subreq);
3211 5 : DBG_DEBUG("close returned %s\n", nt_errstr(status));
3212 5 : if (tevent_req_nterror(req, status)) {
3213 0 : return;
3214 : }
3215 : }
3216 :
3217 5 : static void lock12_read(struct tevent_req *subreq)
3218 : {
3219 5 : struct tevent_req *req = tevent_req_callback_data(
3220 : subreq, struct tevent_req);
3221 5 : struct lock12_state *state = tevent_req_data(
3222 : req, struct lock12_state);
3223 : NTSTATUS status, lock_status, read_status;
3224 5 : uint8_t *buf = NULL;
3225 :
3226 5 : status = lockread_recv(
3227 : subreq, &lock_status, &read_status, state, &buf);
3228 5 : TALLOC_FREE(subreq);
3229 10 : if (tevent_req_nterror(req, status) ||
3230 10 : tevent_req_nterror(req, lock_status) ||
3231 5 : tevent_req_nterror(req, read_status)) {
3232 4 : return;
3233 : }
3234 1 : tevent_req_done(req);
3235 : }
3236 :
3237 5 : static NTSTATUS lock12_recv(struct tevent_req *req)
3238 :
3239 : {
3240 : NTSTATUS status;
3241 :
3242 5 : if (tevent_req_is_nterror(req, &status)) {
3243 4 : return status;
3244 : }
3245 1 : return NT_STATUS_OK;
3246 : }
3247 :
3248 5 : static bool run_locktest12(int dummy)
3249 : {
3250 5 : struct tevent_context *ev = NULL;
3251 5 : struct tevent_req *req = NULL;
3252 5 : struct cli_state *cli = NULL;
3253 5 : const char fname[] = "\\lockt12.lck";
3254 : uint16_t fnum1, fnum2;
3255 5 : bool ret = false;
3256 : bool ok;
3257 5 : uint8_t data = 1;
3258 : NTSTATUS status;
3259 :
3260 5 : printf("starting locktest12\n");
3261 :
3262 5 : ev = samba_tevent_context_init(NULL);
3263 5 : if (ev == NULL) {
3264 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3265 0 : goto done;
3266 : }
3267 :
3268 5 : ok = torture_open_connection(&cli, 0);
3269 5 : if (!ok) {
3270 0 : goto done;
3271 : }
3272 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3273 :
3274 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3275 5 : if (!NT_STATUS_IS_OK(status)) {
3276 0 : d_fprintf(stderr,
3277 : "cli_openx failed: %s\n",
3278 : nt_errstr(status));
3279 0 : goto done;
3280 : }
3281 :
3282 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3283 5 : if (!NT_STATUS_IS_OK(status)) {
3284 0 : d_fprintf(stderr,
3285 : "cli_openx failed: %s\n",
3286 : nt_errstr(status));
3287 0 : goto done;
3288 : }
3289 :
3290 5 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3291 5 : if (!NT_STATUS_IS_OK(status)) {
3292 0 : d_fprintf(stderr,
3293 : "cli_writeall failed: %s\n",
3294 : nt_errstr(status));
3295 0 : goto done;
3296 : }
3297 :
3298 5 : status = cli_locktype(
3299 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3300 5 : if (!NT_STATUS_IS_OK(status)) {
3301 0 : d_fprintf(stderr,
3302 : "cli_locktype failed: %s\n",
3303 : nt_errstr(status));
3304 0 : goto done;
3305 : }
3306 :
3307 5 : req = lock12_send(ev, ev, cli, fnum1, fnum2);
3308 5 : if (req == NULL) {
3309 0 : d_fprintf(stderr, "lock12_send failed\n");
3310 0 : goto done;
3311 : }
3312 :
3313 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3314 5 : if (!ok) {
3315 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3316 0 : goto done;
3317 : }
3318 :
3319 5 : if (!NT_STATUS_IS_OK(status)) {
3320 0 : d_fprintf(stderr,
3321 : "tevent_req_poll_ntstatus returned %s\n",
3322 : nt_errstr(status));
3323 0 : goto done;
3324 : }
3325 :
3326 5 : status = lock12_recv(req);
3327 5 : if (!NT_STATUS_IS_OK(status)) {
3328 4 : d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3329 4 : goto done;
3330 : }
3331 :
3332 1 : ret = true;
3333 5 : done:
3334 5 : if (cli != NULL) {
3335 5 : torture_close_connection(cli);
3336 : }
3337 5 : return ret;
3338 : }
3339 :
3340 : struct lock_ntcancel_state {
3341 : struct timeval start;
3342 : struct smb1_lock_element lck;
3343 : struct tevent_req *subreq;
3344 : };
3345 :
3346 : static void lock_ntcancel_waited(struct tevent_req *subreq);
3347 : static void lock_ntcancel_done(struct tevent_req *subreq);
3348 :
3349 5 : static struct tevent_req *lock_ntcancel_send(
3350 : TALLOC_CTX *mem_ctx,
3351 : struct tevent_context *ev,
3352 : struct cli_state *cli,
3353 : uint16_t fnum)
3354 : {
3355 5 : struct tevent_req *req = NULL, *subreq = NULL;
3356 5 : struct lock_ntcancel_state *state = NULL;
3357 :
3358 5 : req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3359 5 : if (req == NULL) {
3360 0 : return NULL;
3361 : }
3362 10 : state->lck = (struct smb1_lock_element) {
3363 5 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3364 : };
3365 5 : state->start = timeval_current();
3366 :
3367 5 : state->subreq = cli_lockingx_send(
3368 : state, /* mem_ctx */
3369 : ev, /* tevent_context */
3370 : cli, /* cli */
3371 : fnum, /* fnum */
3372 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3373 : 0, /* newoplocklevel */
3374 : 10000, /* timeout */
3375 : 0, /* num_unlocks */
3376 : NULL, /* unlocks */
3377 : 1, /* num_locks */
3378 5 : &state->lck); /* locks */
3379 5 : if (tevent_req_nomem(state->subreq, req)) {
3380 0 : return tevent_req_post(req, ev);
3381 : }
3382 5 : tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3383 :
3384 5 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3385 5 : if (tevent_req_nomem(subreq, req)) {
3386 0 : return tevent_req_post(req, ev);
3387 : }
3388 5 : tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3389 5 : return req;
3390 : }
3391 :
3392 5 : static void lock_ntcancel_waited(struct tevent_req *subreq)
3393 : {
3394 5 : struct tevent_req *req = tevent_req_callback_data(
3395 : subreq, struct tevent_req);
3396 5 : struct lock_ntcancel_state *state = tevent_req_data(
3397 : req, struct lock_ntcancel_state);
3398 : bool ok;
3399 :
3400 5 : ok = tevent_wakeup_recv(subreq);
3401 5 : TALLOC_FREE(subreq);
3402 5 : if (!ok) {
3403 0 : tevent_req_oom(req);
3404 0 : return;
3405 : }
3406 :
3407 5 : ok = tevent_req_cancel(state->subreq);
3408 5 : if (!ok) {
3409 0 : d_fprintf(stderr, "Could not cancel subreq\n");
3410 0 : tevent_req_oom(req);
3411 0 : return;
3412 : }
3413 : }
3414 :
3415 5 : static void lock_ntcancel_done(struct tevent_req *subreq)
3416 : {
3417 5 : struct tevent_req *req = tevent_req_callback_data(
3418 : subreq, struct tevent_req);
3419 5 : struct lock_ntcancel_state *state = tevent_req_data(
3420 : req, struct lock_ntcancel_state);
3421 : NTSTATUS status;
3422 : double elapsed;
3423 :
3424 5 : status = cli_lockingx_recv(subreq);
3425 5 : TALLOC_FREE(subreq);
3426 :
3427 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3428 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3429 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3430 0 : return;
3431 : }
3432 :
3433 5 : elapsed = timeval_elapsed(&state->start);
3434 :
3435 5 : if (elapsed > 3) {
3436 0 : d_printf("cli_lockingx was too slow, cancel did not work\n");
3437 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3438 0 : return;
3439 : }
3440 :
3441 5 : tevent_req_done(req);
3442 : }
3443 :
3444 5 : static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3445 : {
3446 5 : return tevent_req_simple_recv_ntstatus(req);
3447 : }
3448 :
3449 5 : static bool run_locktest13(int dummy)
3450 : {
3451 5 : struct tevent_context *ev = NULL;
3452 5 : struct tevent_req *req = NULL;
3453 5 : struct cli_state *cli = NULL;
3454 5 : const char fname[] = "\\lockt13.lck";
3455 : uint16_t fnum1, fnum2;
3456 5 : bool ret = false;
3457 : bool ok;
3458 5 : uint8_t data = 1;
3459 : NTSTATUS status;
3460 :
3461 5 : printf("starting locktest13\n");
3462 :
3463 5 : ev = samba_tevent_context_init(NULL);
3464 5 : if (ev == NULL) {
3465 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3466 0 : goto done;
3467 : }
3468 :
3469 5 : ok = torture_open_connection(&cli, 0);
3470 5 : if (!ok) {
3471 0 : goto done;
3472 : }
3473 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3474 :
3475 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3476 5 : if (!NT_STATUS_IS_OK(status)) {
3477 0 : d_fprintf(stderr,
3478 : "cli_openx failed: %s\n",
3479 : nt_errstr(status));
3480 0 : goto done;
3481 : }
3482 :
3483 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3484 5 : if (!NT_STATUS_IS_OK(status)) {
3485 0 : d_fprintf(stderr,
3486 : "cli_openx failed: %s\n",
3487 : nt_errstr(status));
3488 0 : goto done;
3489 : }
3490 :
3491 5 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3492 5 : if (!NT_STATUS_IS_OK(status)) {
3493 0 : d_fprintf(stderr,
3494 : "cli_writeall failed: %s\n",
3495 : nt_errstr(status));
3496 0 : goto done;
3497 : }
3498 :
3499 5 : status = cli_locktype(
3500 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3501 5 : if (!NT_STATUS_IS_OK(status)) {
3502 0 : d_fprintf(stderr,
3503 : "cli_locktype failed: %s\n",
3504 : nt_errstr(status));
3505 0 : goto done;
3506 : }
3507 :
3508 5 : req = lock_ntcancel_send(ev, ev, cli, fnum2);
3509 5 : if (req == NULL) {
3510 0 : d_fprintf(stderr, "lock_ntcancel_send failed\n");
3511 0 : goto done;
3512 : }
3513 :
3514 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3515 5 : if (!ok) {
3516 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3517 0 : goto done;
3518 : }
3519 :
3520 5 : if (!NT_STATUS_IS_OK(status)) {
3521 0 : d_fprintf(stderr,
3522 : "tevent_req_poll_ntstatus returned %s\n",
3523 : nt_errstr(status));
3524 0 : goto done;
3525 : }
3526 :
3527 5 : status = lock_ntcancel_recv(req);
3528 5 : if (!NT_STATUS_IS_OK(status)) {
3529 0 : d_fprintf(stderr,
3530 : "lock_ntcancel returned %s\n",
3531 : nt_errstr(status));
3532 0 : goto done;
3533 : }
3534 :
3535 5 : ret = true;
3536 5 : done:
3537 5 : if (cli != NULL) {
3538 5 : torture_close_connection(cli);
3539 : }
3540 5 : return ret;
3541 : }
3542 :
3543 : /*
3544 : test whether fnums and tids open on one VC are available on another (a major
3545 : security hole)
3546 : */
3547 5 : static bool run_fdpasstest(int dummy)
3548 : {
3549 : struct cli_state *cli1, *cli2;
3550 5 : const char *fname = "\\fdpass.tst";
3551 : uint16_t fnum1;
3552 : char buf[1024];
3553 : NTSTATUS status;
3554 :
3555 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3556 0 : return False;
3557 : }
3558 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3559 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
3560 :
3561 5 : printf("starting fdpasstest\n");
3562 :
3563 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3564 :
3565 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3566 : &fnum1);
3567 5 : if (!NT_STATUS_IS_OK(status)) {
3568 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3569 0 : return False;
3570 : }
3571 :
3572 5 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3573 : 13, NULL);
3574 5 : if (!NT_STATUS_IS_OK(status)) {
3575 0 : printf("write failed (%s)\n", nt_errstr(status));
3576 0 : return False;
3577 : }
3578 :
3579 5 : cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3580 5 : cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3581 5 : cli_setpid(cli2, cli_getpid(cli1));
3582 :
3583 5 : if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3584 0 : printf("read succeeded! nasty security hole [%s]\n", buf);
3585 0 : return false;
3586 : }
3587 :
3588 5 : cli_close(cli1, fnum1);
3589 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3590 :
3591 5 : torture_close_connection(cli1);
3592 5 : torture_close_connection(cli2);
3593 :
3594 5 : printf("finished fdpasstest\n");
3595 5 : return True;
3596 : }
3597 :
3598 5 : static bool run_fdsesstest(int dummy)
3599 : {
3600 : struct cli_state *cli;
3601 : uint16_t new_vuid;
3602 : uint16_t saved_vuid;
3603 : uint32_t new_cnum;
3604 : uint32_t saved_cnum;
3605 5 : const char *fname = "\\fdsess.tst";
3606 5 : const char *fname1 = "\\fdsess1.tst";
3607 : uint16_t fnum1;
3608 : uint16_t fnum2;
3609 : char buf[1024];
3610 5 : bool ret = True;
3611 : NTSTATUS status;
3612 :
3613 5 : if (!torture_open_connection(&cli, 0))
3614 0 : return False;
3615 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3616 :
3617 5 : if (!torture_cli_session_setup2(cli, &new_vuid))
3618 0 : return False;
3619 :
3620 5 : saved_cnum = cli_state_get_tid(cli);
3621 5 : if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3622 0 : return False;
3623 5 : new_cnum = cli_state_get_tid(cli);
3624 5 : cli_state_set_tid(cli, saved_cnum);
3625 :
3626 5 : printf("starting fdsesstest\n");
3627 :
3628 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3629 5 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3630 :
3631 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3632 5 : if (!NT_STATUS_IS_OK(status)) {
3633 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3634 0 : return False;
3635 : }
3636 :
3637 5 : status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3638 : NULL);
3639 5 : if (!NT_STATUS_IS_OK(status)) {
3640 0 : printf("write failed (%s)\n", nt_errstr(status));
3641 0 : return False;
3642 : }
3643 :
3644 5 : saved_vuid = cli_state_get_uid(cli);
3645 5 : cli_state_set_uid(cli, new_vuid);
3646 :
3647 5 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3648 0 : printf("read succeeded with different vuid! "
3649 : "nasty security hole [%s]\n", buf);
3650 0 : ret = false;
3651 : }
3652 : /* Try to open a file with different vuid, samba cnum. */
3653 5 : if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3654 5 : printf("create with different vuid, same cnum succeeded.\n");
3655 5 : cli_close(cli, fnum2);
3656 5 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3657 : } else {
3658 0 : printf("create with different vuid, same cnum failed.\n");
3659 0 : printf("This will cause problems with service clients.\n");
3660 0 : ret = False;
3661 : }
3662 :
3663 5 : cli_state_set_uid(cli, saved_vuid);
3664 :
3665 : /* Try with same vuid, different cnum. */
3666 5 : cli_state_set_tid(cli, new_cnum);
3667 :
3668 5 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3669 0 : printf("read succeeded with different cnum![%s]\n", buf);
3670 0 : ret = false;
3671 : }
3672 :
3673 5 : cli_state_set_tid(cli, saved_cnum);
3674 5 : cli_close(cli, fnum1);
3675 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3676 :
3677 5 : torture_close_connection(cli);
3678 :
3679 5 : printf("finished fdsesstest\n");
3680 5 : return ret;
3681 : }
3682 :
3683 : /*
3684 : This test checks that
3685 :
3686 : 1) the server does not allow an unlink on a file that is open
3687 : */
3688 5 : static bool run_unlinktest(int dummy)
3689 : {
3690 : struct cli_state *cli;
3691 5 : const char *fname = "\\unlink.tst";
3692 : uint16_t fnum;
3693 5 : bool correct = True;
3694 : NTSTATUS status;
3695 :
3696 5 : if (!torture_open_connection(&cli, 0)) {
3697 0 : return False;
3698 : }
3699 :
3700 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3701 :
3702 5 : printf("starting unlink test\n");
3703 :
3704 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3705 :
3706 5 : cli_setpid(cli, 1);
3707 :
3708 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3709 5 : if (!NT_STATUS_IS_OK(status)) {
3710 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3711 0 : return False;
3712 : }
3713 :
3714 5 : status = cli_unlink(cli, fname,
3715 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3716 5 : if (NT_STATUS_IS_OK(status)) {
3717 0 : printf("error: server allowed unlink on an open file\n");
3718 0 : correct = False;
3719 : } else {
3720 5 : correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3721 5 : NT_STATUS_SHARING_VIOLATION);
3722 : }
3723 :
3724 5 : cli_close(cli, fnum);
3725 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3726 :
3727 5 : if (!torture_close_connection(cli)) {
3728 0 : correct = False;
3729 : }
3730 :
3731 5 : printf("unlink test finished\n");
3732 :
3733 5 : return correct;
3734 : }
3735 :
3736 :
3737 : /*
3738 : test how many open files this server supports on the one socket
3739 : */
3740 0 : static bool run_maxfidtest(int dummy)
3741 : {
3742 : struct cli_state *cli;
3743 : fstring fname;
3744 : uint16_t fnums[0x11000];
3745 : int i;
3746 0 : int retries=4;
3747 0 : bool correct = True;
3748 : NTSTATUS status;
3749 :
3750 0 : cli = current_cli;
3751 :
3752 0 : if (retries <= 0) {
3753 0 : printf("failed to connect\n");
3754 0 : return False;
3755 : }
3756 :
3757 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3758 :
3759 0 : for (i=0; i<0x11000; i++) {
3760 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3761 0 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3762 : &fnums[i]);
3763 0 : if (!NT_STATUS_IS_OK(status)) {
3764 0 : printf("open of %s failed (%s)\n",
3765 : fname, nt_errstr(status));
3766 0 : printf("maximum fnum is %d\n", i);
3767 0 : break;
3768 : }
3769 0 : printf("%6d\r", i);
3770 : }
3771 0 : printf("%6d\n", i);
3772 0 : i--;
3773 :
3774 0 : printf("cleaning up\n");
3775 0 : for (;i>=0;i--) {
3776 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3777 0 : cli_close(cli, fnums[i]);
3778 :
3779 0 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3780 0 : if (!NT_STATUS_IS_OK(status)) {
3781 0 : printf("unlink of %s failed (%s)\n",
3782 : fname, nt_errstr(status));
3783 0 : correct = False;
3784 : }
3785 0 : printf("%6d\r", i);
3786 : }
3787 0 : printf("%6d\n", 0);
3788 :
3789 0 : printf("maxfid test finished\n");
3790 0 : if (!torture_close_connection(cli)) {
3791 0 : correct = False;
3792 : }
3793 0 : return correct;
3794 : }
3795 :
3796 : /* generate a random buffer */
3797 0 : static void rand_buf(char *buf, int len)
3798 : {
3799 0 : while (len--) {
3800 0 : *buf = (char)sys_random();
3801 0 : buf++;
3802 : }
3803 0 : }
3804 :
3805 : /* send smb negprot commands, not reading the response */
3806 0 : static bool run_negprot_nowait(int dummy)
3807 : {
3808 : struct tevent_context *ev;
3809 : int i;
3810 : struct cli_state *cli;
3811 0 : bool correct = True;
3812 :
3813 0 : printf("starting negprot nowait test\n");
3814 :
3815 0 : ev = samba_tevent_context_init(talloc_tos());
3816 0 : if (ev == NULL) {
3817 0 : return false;
3818 : }
3819 :
3820 0 : if (!(cli = open_nbt_connection())) {
3821 0 : TALLOC_FREE(ev);
3822 0 : return False;
3823 : }
3824 :
3825 0 : for (i=0;i<50000;i++) {
3826 : struct tevent_req *req;
3827 :
3828 0 : req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3829 : PROTOCOL_CORE, PROTOCOL_NT1, 0);
3830 0 : if (req == NULL) {
3831 0 : TALLOC_FREE(ev);
3832 0 : return false;
3833 : }
3834 0 : if (!tevent_req_poll(req, ev)) {
3835 0 : d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3836 0 : strerror(errno));
3837 0 : TALLOC_FREE(ev);
3838 0 : return false;
3839 : }
3840 0 : TALLOC_FREE(req);
3841 : }
3842 :
3843 0 : if (torture_close_connection(cli)) {
3844 0 : correct = False;
3845 : }
3846 :
3847 0 : printf("finished negprot nowait test\n");
3848 :
3849 0 : return correct;
3850 : }
3851 :
3852 : /* send smb negprot commands, not reading the response */
3853 4 : static bool run_bad_nbt_session(int dummy)
3854 : {
3855 : struct nmb_name called, calling;
3856 : struct sockaddr_storage ss;
3857 : NTSTATUS status;
3858 : int fd;
3859 : bool ret;
3860 :
3861 4 : printf("starting bad nbt session test\n");
3862 :
3863 4 : make_nmb_name(&calling, myname, 0x0);
3864 4 : make_nmb_name(&called , host, 0x20);
3865 :
3866 4 : if (!resolve_name(host, &ss, 0x20, true)) {
3867 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
3868 0 : return false;
3869 : }
3870 :
3871 4 : status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3872 4 : if (!NT_STATUS_IS_OK(status)) {
3873 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
3874 : nt_errstr(status));
3875 0 : return false;
3876 : }
3877 :
3878 4 : ret = cli_bad_session_request(fd, &calling, &called);
3879 4 : close(fd);
3880 4 : if (!ret) {
3881 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
3882 : nt_errstr(status));
3883 0 : return false;
3884 : }
3885 :
3886 4 : printf("finished bad nbt session test\n");
3887 4 : return true;
3888 : }
3889 :
3890 : /* send random IPC commands */
3891 0 : static bool run_randomipc(int dummy)
3892 : {
3893 0 : char *rparam = NULL;
3894 0 : char *rdata = NULL;
3895 : unsigned int rdrcnt,rprcnt;
3896 : char param[1024];
3897 : int api, param_len, i;
3898 : struct cli_state *cli;
3899 0 : bool correct = True;
3900 0 : int count = 50000;
3901 :
3902 0 : printf("starting random ipc test\n");
3903 :
3904 0 : if (!torture_open_connection(&cli, 0)) {
3905 0 : return False;
3906 : }
3907 :
3908 0 : for (i=0;i<count;i++) {
3909 0 : api = sys_random() % 500;
3910 0 : param_len = (sys_random() % 64);
3911 :
3912 0 : rand_buf(param, param_len);
3913 :
3914 0 : SSVAL(param,0,api);
3915 :
3916 0 : cli_api(cli,
3917 : param, param_len, 8,
3918 : NULL, 0, CLI_BUFFER_SIZE,
3919 : &rparam, &rprcnt,
3920 : &rdata, &rdrcnt);
3921 0 : if (i % 100 == 0) {
3922 0 : printf("%d/%d\r", i,count);
3923 : }
3924 : }
3925 0 : printf("%d/%d\n", i, count);
3926 :
3927 0 : if (!torture_close_connection(cli)) {
3928 0 : correct = False;
3929 : }
3930 :
3931 0 : SAFE_FREE(rparam);
3932 0 : SAFE_FREE(rdata);
3933 :
3934 0 : printf("finished random ipc test\n");
3935 :
3936 0 : return correct;
3937 : }
3938 :
3939 :
3940 :
3941 8 : static void browse_callback(const char *sname, uint32_t stype,
3942 : const char *comment, void *state)
3943 : {
3944 8 : printf("\t%20.20s %08x %s\n", sname, stype, comment);
3945 8 : }
3946 :
3947 :
3948 :
3949 : /*
3950 : This test checks the browse list code
3951 :
3952 : */
3953 5 : static bool run_browsetest(int dummy)
3954 : {
3955 : static struct cli_state *cli;
3956 5 : bool correct = True;
3957 :
3958 5 : printf("starting browse test\n");
3959 :
3960 5 : if (!torture_open_connection(&cli, 0)) {
3961 0 : return False;
3962 : }
3963 :
3964 5 : printf("domain list:\n");
3965 5 : cli_NetServerEnum(cli, cli->server_domain,
3966 : SV_TYPE_DOMAIN_ENUM,
3967 : browse_callback, NULL);
3968 :
3969 5 : printf("machine list:\n");
3970 5 : cli_NetServerEnum(cli, cli->server_domain,
3971 : SV_TYPE_ALL,
3972 : browse_callback, NULL);
3973 :
3974 5 : if (!torture_close_connection(cli)) {
3975 0 : correct = False;
3976 : }
3977 :
3978 5 : printf("browse test finished\n");
3979 :
3980 5 : return correct;
3981 :
3982 : }
3983 :
3984 20 : static bool check_attributes(struct cli_state *cli,
3985 : const char *fname,
3986 : uint32_t expected_attrs)
3987 : {
3988 20 : uint32_t attrs = 0;
3989 20 : NTSTATUS status = cli_getatr(cli,
3990 : fname,
3991 : &attrs,
3992 : NULL,
3993 : NULL);
3994 20 : if (!NT_STATUS_IS_OK(status)) {
3995 0 : printf("cli_getatr failed with %s\n",
3996 : nt_errstr(status));
3997 0 : return false;
3998 : }
3999 20 : if (attrs != expected_attrs) {
4000 0 : printf("Attributes incorrect 0x%x, should be 0x%x\n",
4001 : (unsigned int)attrs,
4002 : (unsigned int)expected_attrs);
4003 0 : return false;
4004 : }
4005 20 : return true;
4006 : }
4007 :
4008 : /*
4009 : This checks how the getatr calls works
4010 : */
4011 5 : static bool run_attrtest(int dummy)
4012 : {
4013 : struct cli_state *cli;
4014 : uint16_t fnum;
4015 : time_t t, t2;
4016 5 : const char *fname = "\\attrib123456789.tst";
4017 5 : bool correct = True;
4018 : NTSTATUS status;
4019 :
4020 5 : printf("starting attrib test\n");
4021 :
4022 5 : if (!torture_open_connection(&cli, 0)) {
4023 0 : return False;
4024 : }
4025 :
4026 : /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4027 5 : status = cli_unlink(cli, fname, 0x20000);
4028 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4029 0 : correct = false;
4030 0 : goto out;
4031 : }
4032 :
4033 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4034 5 : cli_openx(cli, fname,
4035 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4036 5 : cli_close(cli, fnum);
4037 :
4038 5 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4039 5 : if (!NT_STATUS_IS_OK(status)) {
4040 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4041 0 : correct = False;
4042 : }
4043 :
4044 5 : if (labs(t - time(NULL)) > 60*60*24*10) {
4045 0 : printf("ERROR: SMBgetatr bug. time is %s",
4046 : ctime(&t));
4047 0 : t = time(NULL);
4048 0 : correct = True;
4049 : }
4050 :
4051 5 : t2 = t-60*60*24; /* 1 day ago */
4052 :
4053 : /* Ensure we can't set with out-of-range (unknown) attribute. */
4054 5 : status = cli_setatr(cli, fname, 0x20000, t2);
4055 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4056 0 : correct = false;
4057 0 : goto out;
4058 : }
4059 :
4060 5 : status = cli_setatr(cli, fname, 0, t2);
4061 5 : if (!NT_STATUS_IS_OK(status)) {
4062 0 : printf("setatr failed (%s)\n", nt_errstr(status));
4063 0 : correct = True;
4064 : }
4065 :
4066 5 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4067 5 : if (!NT_STATUS_IS_OK(status)) {
4068 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4069 0 : correct = True;
4070 : }
4071 :
4072 5 : if (t != t2) {
4073 0 : printf("ERROR: getatr/setatr bug. times are\n%s",
4074 : ctime(&t));
4075 0 : printf("%s", ctime(&t2));
4076 0 : correct = True;
4077 : }
4078 :
4079 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4080 :
4081 : /* Check cli_setpathinfo_ext() */
4082 : /* Re-create the file. */
4083 5 : status = cli_openx(cli, fname,
4084 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4085 5 : if (!NT_STATUS_IS_OK(status)) {
4086 0 : printf("Failed to recreate %s (%s)\n",
4087 : fname, nt_errstr(status));
4088 0 : correct = false;
4089 : }
4090 5 : cli_close(cli, fnum);
4091 :
4092 5 : status = cli_setpathinfo_ext(
4093 : cli,
4094 : fname,
4095 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4096 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4097 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4098 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4099 : FILE_ATTRIBUTE_SYSTEM |
4100 : FILE_ATTRIBUTE_HIDDEN |
4101 : FILE_ATTRIBUTE_READONLY);
4102 5 : if (!NT_STATUS_IS_OK(status)) {
4103 0 : printf("cli_setpathinfo_ext failed with %s\n",
4104 : nt_errstr(status));
4105 0 : correct = false;
4106 : }
4107 :
4108 : /* Check attributes are correct. */
4109 5 : correct = check_attributes(cli,
4110 : fname,
4111 : FILE_ATTRIBUTE_SYSTEM |
4112 : FILE_ATTRIBUTE_HIDDEN |
4113 : FILE_ATTRIBUTE_READONLY);
4114 5 : if (correct == false) {
4115 0 : goto out;
4116 : }
4117 :
4118 : /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4119 5 : status = cli_setpathinfo_ext(
4120 : cli,
4121 : fname,
4122 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4123 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4124 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4125 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4126 : FILE_ATTRIBUTE_NORMAL);
4127 5 : if (!NT_STATUS_IS_OK(status)) {
4128 0 : printf("cli_setpathinfo_ext failed with %s\n",
4129 : nt_errstr(status));
4130 0 : correct = false;
4131 : }
4132 :
4133 : /* Check attributes are correct. */
4134 5 : correct = check_attributes(cli,
4135 : fname,
4136 : FILE_ATTRIBUTE_SYSTEM |
4137 : FILE_ATTRIBUTE_HIDDEN |
4138 : FILE_ATTRIBUTE_READONLY);
4139 5 : if (correct == false) {
4140 0 : goto out;
4141 : }
4142 :
4143 : /* Setting to (uint16_t)-1 should also be ignored. */
4144 5 : status = cli_setpathinfo_ext(
4145 : cli,
4146 : fname,
4147 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4148 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4149 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4150 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4151 : (uint32_t)-1);
4152 5 : if (!NT_STATUS_IS_OK(status)) {
4153 0 : printf("cli_setpathinfo_ext failed with %s\n",
4154 : nt_errstr(status));
4155 0 : correct = false;
4156 : }
4157 :
4158 : /* Check attributes are correct. */
4159 5 : correct = check_attributes(cli,
4160 : fname,
4161 : FILE_ATTRIBUTE_SYSTEM |
4162 : FILE_ATTRIBUTE_HIDDEN |
4163 : FILE_ATTRIBUTE_READONLY);
4164 5 : if (correct == false) {
4165 0 : goto out;
4166 : }
4167 :
4168 : /* Setting to 0 should clear them all. */
4169 5 : status = cli_setpathinfo_ext(
4170 : cli,
4171 : fname,
4172 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4173 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4174 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4175 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4176 : 0);
4177 5 : if (!NT_STATUS_IS_OK(status)) {
4178 0 : printf("cli_setpathinfo_ext failed with %s\n",
4179 : nt_errstr(status));
4180 0 : correct = false;
4181 : }
4182 :
4183 : /* Check attributes are correct. */
4184 5 : correct = check_attributes(cli,
4185 : fname,
4186 : FILE_ATTRIBUTE_NORMAL);
4187 5 : if (correct == false) {
4188 0 : goto out;
4189 : }
4190 :
4191 10 : out:
4192 :
4193 5 : cli_unlink(cli,
4194 : fname,
4195 : FILE_ATTRIBUTE_SYSTEM |
4196 : FILE_ATTRIBUTE_HIDDEN|
4197 : FILE_ATTRIBUTE_READONLY);
4198 :
4199 5 : if (!torture_close_connection(cli)) {
4200 0 : correct = False;
4201 : }
4202 :
4203 5 : printf("attrib test finished\n");
4204 :
4205 5 : return correct;
4206 : }
4207 :
4208 :
4209 : /*
4210 : This checks a couple of trans2 calls
4211 : */
4212 5 : static bool run_trans2test(int dummy)
4213 : {
4214 : struct cli_state *cli;
4215 : uint16_t fnum;
4216 : off_t size;
4217 : time_t c_time, a_time, m_time;
4218 : struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4219 5 : const char *fname = "\\trans2.tst";
4220 5 : const char *dname = "\\trans2";
4221 5 : const char *fname2 = "\\trans2\\trans2.tst";
4222 : char *pname;
4223 5 : bool correct = True;
4224 : NTSTATUS status;
4225 : uint32_t fs_attr;
4226 : uint64_t ino;
4227 :
4228 5 : printf("starting trans2 test\n");
4229 :
4230 5 : if (!torture_open_connection(&cli, 0)) {
4231 0 : return False;
4232 : }
4233 :
4234 5 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4235 : /* Ensure ino is zero, SMB2 gets a real one. */
4236 0 : ino = 0;
4237 : } else {
4238 : /* Ensure ino is -1, SMB1 never gets a real one. */
4239 5 : ino = (uint64_t)-1;
4240 : }
4241 :
4242 5 : status = cli_get_fs_attr_info(cli, &fs_attr);
4243 5 : if (!NT_STATUS_IS_OK(status)) {
4244 0 : printf("ERROR: cli_get_fs_attr_info returned %s\n",
4245 : nt_errstr(status));
4246 0 : correct = false;
4247 : }
4248 :
4249 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4250 5 : cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4251 5 : status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4252 : &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4253 5 : if (!NT_STATUS_IS_OK(status)) {
4254 0 : printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4255 0 : correct = False;
4256 : }
4257 :
4258 5 : status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4259 5 : if (!NT_STATUS_IS_OK(status)) {
4260 0 : printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4261 0 : correct = False;
4262 : }
4263 5 : else if (strcmp(pname, fname)) {
4264 0 : printf("qfilename gave different name? [%s] [%s]\n",
4265 : fname, pname);
4266 0 : correct = False;
4267 : }
4268 :
4269 5 : cli_close(cli, fnum);
4270 :
4271 5 : sleep(2);
4272 :
4273 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4274 5 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4275 : &fnum);
4276 5 : if (!NT_STATUS_IS_OK(status)) {
4277 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4278 0 : return False;
4279 : }
4280 5 : cli_close(cli, fnum);
4281 :
4282 5 : status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4283 : NULL);
4284 5 : if (!NT_STATUS_IS_OK(status)) {
4285 0 : printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4286 0 : correct = False;
4287 : } else {
4288 5 : time_t t = time(NULL);
4289 :
4290 5 : if (c_time != m_time) {
4291 0 : printf("create time=%s", ctime(&c_time));
4292 0 : printf("modify time=%s", ctime(&m_time));
4293 0 : printf("This system appears to have sticky create times\n");
4294 : }
4295 5 : if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4296 0 : printf("access time=%s", ctime(&a_time));
4297 0 : printf("This system appears to set a midnight access time\n");
4298 0 : correct = False;
4299 : }
4300 :
4301 5 : if (labs(m_time - t) > 60*60*24*7) {
4302 0 : printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4303 0 : correct = False;
4304 : }
4305 : }
4306 :
4307 :
4308 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4309 5 : cli_openx(cli, fname,
4310 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4311 5 : cli_close(cli, fnum);
4312 5 : status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4313 : &m_time_ts, &size, NULL, &ino);
4314 5 : if (!NT_STATUS_IS_OK(status)) {
4315 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4316 0 : correct = False;
4317 : } else {
4318 5 : if (w_time_ts.tv_sec < 60*60*24*2) {
4319 0 : printf("write time=%s", ctime(&w_time_ts.tv_sec));
4320 0 : printf("This system appears to set a initial 0 write time\n");
4321 0 : correct = False;
4322 : }
4323 5 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4324 : /* SMB2 should always return an inode. */
4325 0 : if (ino == 0) {
4326 0 : printf("SMB2 bad inode (0)\n");
4327 0 : correct = false;
4328 : }
4329 : } else {
4330 : /* SMB1 must always return zero here. */
4331 5 : if (ino != 0) {
4332 0 : printf("SMB1 bad inode (!0)\n");
4333 0 : correct = false;
4334 : }
4335 : }
4336 : }
4337 :
4338 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4339 :
4340 :
4341 : /* check if the server updates the directory modification time
4342 : when creating a new file */
4343 5 : status = cli_mkdir(cli, dname);
4344 5 : if (!NT_STATUS_IS_OK(status)) {
4345 0 : printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4346 0 : correct = False;
4347 : }
4348 5 : sleep(3);
4349 5 : status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4350 : &w_time_ts, &m_time_ts, &size, NULL, NULL);
4351 5 : if (!NT_STATUS_IS_OK(status)) {
4352 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4353 0 : correct = False;
4354 : }
4355 :
4356 5 : cli_openx(cli, fname2,
4357 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4358 5 : cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4359 5 : cli_close(cli, fnum);
4360 5 : status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4361 : &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4362 5 : if (!NT_STATUS_IS_OK(status)) {
4363 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4364 0 : correct = False;
4365 : } else {
4366 5 : if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4367 : == 0) {
4368 0 : printf("This system does not update directory modification times\n");
4369 0 : correct = False;
4370 : }
4371 : }
4372 5 : cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4373 5 : cli_rmdir(cli, dname);
4374 :
4375 5 : if (!torture_close_connection(cli)) {
4376 0 : correct = False;
4377 : }
4378 :
4379 5 : printf("trans2 test finished\n");
4380 :
4381 5 : return correct;
4382 : }
4383 :
4384 : /*
4385 : This checks new W2K calls.
4386 : */
4387 :
4388 180 : static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4389 : {
4390 180 : uint8_t *buf = NULL;
4391 : uint32_t len;
4392 : NTSTATUS status;
4393 :
4394 180 : status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4395 : CLI_BUFFER_SIZE, NULL, &buf, &len);
4396 180 : if (!NT_STATUS_IS_OK(status)) {
4397 180 : printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4398 : nt_errstr(status));
4399 : } else {
4400 0 : printf("qfileinfo: level %d, len = %u\n", level, len);
4401 0 : dump_data(0, (uint8_t *)buf, len);
4402 0 : printf("\n");
4403 : }
4404 180 : TALLOC_FREE(buf);
4405 180 : return status;
4406 : }
4407 :
4408 5 : static bool run_w2ktest(int dummy)
4409 : {
4410 : struct cli_state *cli;
4411 : uint16_t fnum;
4412 5 : const char *fname = "\\w2ktest\\w2k.tst";
4413 : int level;
4414 5 : bool correct = True;
4415 :
4416 5 : printf("starting w2k test\n");
4417 :
4418 5 : if (!torture_open_connection(&cli, 0)) {
4419 0 : return False;
4420 : }
4421 :
4422 5 : cli_openx(cli, fname,
4423 : O_RDWR | O_CREAT , DENY_NONE, &fnum);
4424 :
4425 185 : for (level = 1004; level < 1040; level++) {
4426 180 : new_trans(cli, fnum, level);
4427 : }
4428 :
4429 5 : cli_close(cli, fnum);
4430 :
4431 5 : if (!torture_close_connection(cli)) {
4432 0 : correct = False;
4433 : }
4434 :
4435 5 : printf("w2k test finished\n");
4436 :
4437 5 : return correct;
4438 : }
4439 :
4440 :
4441 : /*
4442 : this is a harness for some oplock tests
4443 : */
4444 5 : static bool run_oplock1(int dummy)
4445 : {
4446 : struct cli_state *cli1;
4447 5 : const char *fname = "\\lockt1.lck";
4448 : uint16_t fnum1;
4449 5 : bool correct = True;
4450 : NTSTATUS status;
4451 :
4452 5 : printf("starting oplock test 1\n");
4453 :
4454 5 : if (!torture_open_connection(&cli1, 0)) {
4455 0 : return False;
4456 : }
4457 :
4458 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4459 :
4460 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4461 :
4462 5 : cli1->use_oplocks = True;
4463 :
4464 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4465 : &fnum1);
4466 5 : if (!NT_STATUS_IS_OK(status)) {
4467 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4468 0 : return False;
4469 : }
4470 :
4471 5 : cli1->use_oplocks = False;
4472 :
4473 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4474 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4475 :
4476 5 : status = cli_close(cli1, fnum1);
4477 5 : if (!NT_STATUS_IS_OK(status)) {
4478 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4479 0 : return False;
4480 : }
4481 :
4482 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4483 5 : if (!NT_STATUS_IS_OK(status)) {
4484 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4485 0 : return False;
4486 : }
4487 :
4488 5 : if (!torture_close_connection(cli1)) {
4489 0 : correct = False;
4490 : }
4491 :
4492 5 : printf("finished oplock test 1\n");
4493 :
4494 5 : return correct;
4495 : }
4496 :
4497 4 : static bool run_oplock2(int dummy)
4498 : {
4499 : struct cli_state *cli1, *cli2;
4500 4 : const char *fname = "\\lockt2.lck";
4501 : uint16_t fnum1, fnum2;
4502 4 : int saved_use_oplocks = use_oplocks;
4503 : char buf[4];
4504 4 : bool correct = True;
4505 : volatile bool *shared_correct;
4506 : size_t nread;
4507 : NTSTATUS status;
4508 :
4509 4 : shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4510 4 : *shared_correct = True;
4511 :
4512 4 : use_level_II_oplocks = True;
4513 4 : use_oplocks = True;
4514 :
4515 4 : printf("starting oplock test 2\n");
4516 :
4517 4 : if (!torture_open_connection(&cli1, 0)) {
4518 0 : use_level_II_oplocks = False;
4519 0 : use_oplocks = saved_use_oplocks;
4520 0 : return False;
4521 : }
4522 :
4523 4 : if (!torture_open_connection(&cli2, 1)) {
4524 0 : use_level_II_oplocks = False;
4525 0 : use_oplocks = saved_use_oplocks;
4526 0 : return False;
4527 : }
4528 :
4529 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4530 :
4531 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4532 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4533 :
4534 4 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4535 : &fnum1);
4536 4 : if (!NT_STATUS_IS_OK(status)) {
4537 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4538 0 : return False;
4539 : }
4540 :
4541 : /* Don't need the globals any more. */
4542 4 : use_level_II_oplocks = False;
4543 4 : use_oplocks = saved_use_oplocks;
4544 :
4545 4 : if (fork() == 0) {
4546 : /* Child code */
4547 4 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4548 4 : if (!NT_STATUS_IS_OK(status)) {
4549 0 : printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4550 0 : *shared_correct = False;
4551 0 : exit(0);
4552 : }
4553 :
4554 4 : sleep(2);
4555 :
4556 4 : status = cli_close(cli2, fnum2);
4557 4 : if (!NT_STATUS_IS_OK(status)) {
4558 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4559 0 : *shared_correct = False;
4560 : }
4561 :
4562 4 : exit(0);
4563 : }
4564 :
4565 4 : sleep(2);
4566 :
4567 : /* Ensure cli1 processes the break. Empty file should always return 0
4568 : * bytes. */
4569 4 : status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4570 4 : if (!NT_STATUS_IS_OK(status)) {
4571 0 : printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4572 0 : correct = false;
4573 4 : } else if (nread != 0) {
4574 0 : printf("read on empty fnum1 failed. recv %ld expected %d\n",
4575 : (unsigned long)nread, 0);
4576 0 : correct = false;
4577 : }
4578 :
4579 : /* Should now be at level II. */
4580 : /* Test if sending a write locks causes a break to none. */
4581 4 : status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4582 4 : if (!NT_STATUS_IS_OK(status)) {
4583 0 : printf("lock failed (%s)\n", nt_errstr(status));
4584 0 : correct = False;
4585 : }
4586 :
4587 4 : cli_unlock(cli1, fnum1, 0, 4);
4588 :
4589 4 : sleep(2);
4590 :
4591 4 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4592 4 : if (!NT_STATUS_IS_OK(status)) {
4593 0 : printf("lock failed (%s)\n", nt_errstr(status));
4594 0 : correct = False;
4595 : }
4596 :
4597 4 : cli_unlock(cli1, fnum1, 0, 4);
4598 :
4599 4 : sleep(2);
4600 :
4601 4 : cli_read(cli1, fnum1, buf, 0, 4, NULL);
4602 :
4603 4 : status = cli_close(cli1, fnum1);
4604 4 : if (!NT_STATUS_IS_OK(status)) {
4605 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4606 0 : correct = False;
4607 : }
4608 :
4609 4 : sleep(4);
4610 :
4611 4 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4612 4 : if (!NT_STATUS_IS_OK(status)) {
4613 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4614 0 : correct = False;
4615 : }
4616 :
4617 4 : if (!torture_close_connection(cli1)) {
4618 0 : correct = False;
4619 : }
4620 :
4621 4 : if (!*shared_correct) {
4622 0 : correct = False;
4623 : }
4624 :
4625 4 : printf("finished oplock test 2\n");
4626 :
4627 4 : return correct;
4628 : }
4629 :
4630 : struct oplock4_state {
4631 : struct tevent_context *ev;
4632 : struct cli_state *cli;
4633 : bool *got_break;
4634 : uint16_t *fnum2;
4635 : };
4636 :
4637 : static void oplock4_got_break(struct tevent_req *req);
4638 : static void oplock4_got_open(struct tevent_req *req);
4639 :
4640 5 : static bool run_oplock4(int dummy)
4641 : {
4642 : struct tevent_context *ev;
4643 : struct cli_state *cli1, *cli2;
4644 : struct tevent_req *oplock_req, *open_req;
4645 5 : const char *fname = "\\lockt4.lck";
4646 5 : const char *fname_ln = "\\lockt4_ln.lck";
4647 : uint16_t fnum1, fnum2;
4648 5 : int saved_use_oplocks = use_oplocks;
4649 : NTSTATUS status;
4650 5 : bool correct = true;
4651 :
4652 : bool got_break;
4653 :
4654 : struct oplock4_state *state;
4655 :
4656 5 : printf("starting oplock test 4\n");
4657 :
4658 5 : if (!torture_open_connection(&cli1, 0)) {
4659 0 : use_level_II_oplocks = false;
4660 0 : use_oplocks = saved_use_oplocks;
4661 0 : return false;
4662 : }
4663 :
4664 5 : if (!torture_open_connection(&cli2, 1)) {
4665 0 : use_level_II_oplocks = false;
4666 0 : use_oplocks = saved_use_oplocks;
4667 0 : return false;
4668 : }
4669 :
4670 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4671 5 : cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4672 :
4673 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4674 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4675 :
4676 : /* Create the file. */
4677 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4678 : &fnum1);
4679 5 : if (!NT_STATUS_IS_OK(status)) {
4680 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4681 0 : return false;
4682 : }
4683 :
4684 5 : status = cli_close(cli1, fnum1);
4685 5 : if (!NT_STATUS_IS_OK(status)) {
4686 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4687 0 : return false;
4688 : }
4689 :
4690 : /* Now create a hardlink. */
4691 5 : status = cli_hardlink(cli1, fname, fname_ln);
4692 5 : if (!NT_STATUS_IS_OK(status)) {
4693 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
4694 0 : return false;
4695 : }
4696 :
4697 : /* Prove that opening hardlinks cause deny modes to conflict. */
4698 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4699 5 : if (!NT_STATUS_IS_OK(status)) {
4700 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4701 0 : return false;
4702 : }
4703 :
4704 5 : status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4705 5 : if (NT_STATUS_IS_OK(status)) {
4706 0 : printf("open of %s succeeded - should fail with sharing violation.\n",
4707 : fname_ln);
4708 0 : return false;
4709 : }
4710 :
4711 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4712 0 : printf("open of %s should fail with sharing violation. Got %s\n",
4713 : fname_ln, nt_errstr(status));
4714 0 : return false;
4715 : }
4716 :
4717 5 : status = cli_close(cli1, fnum1);
4718 5 : if (!NT_STATUS_IS_OK(status)) {
4719 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4720 0 : return false;
4721 : }
4722 :
4723 5 : cli1->use_oplocks = true;
4724 5 : cli2->use_oplocks = true;
4725 :
4726 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4727 5 : if (!NT_STATUS_IS_OK(status)) {
4728 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4729 0 : return false;
4730 : }
4731 :
4732 5 : ev = samba_tevent_context_init(talloc_tos());
4733 5 : if (ev == NULL) {
4734 0 : printf("tevent_context_init failed\n");
4735 0 : return false;
4736 : }
4737 :
4738 5 : state = talloc(ev, struct oplock4_state);
4739 5 : if (state == NULL) {
4740 0 : printf("talloc failed\n");
4741 0 : return false;
4742 : }
4743 5 : state->ev = ev;
4744 5 : state->cli = cli1;
4745 5 : state->got_break = &got_break;
4746 5 : state->fnum2 = &fnum2;
4747 :
4748 5 : oplock_req = cli_smb_oplock_break_waiter_send(
4749 : talloc_tos(), ev, cli1);
4750 5 : if (oplock_req == NULL) {
4751 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
4752 0 : return false;
4753 : }
4754 5 : tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4755 :
4756 5 : open_req = cli_openx_send(
4757 : talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4758 5 : if (open_req == NULL) {
4759 0 : printf("cli_openx_send failed\n");
4760 0 : return false;
4761 : }
4762 5 : tevent_req_set_callback(open_req, oplock4_got_open, state);
4763 :
4764 5 : got_break = false;
4765 5 : fnum2 = 0xffff;
4766 :
4767 45 : while (!got_break || fnum2 == 0xffff) {
4768 : int ret;
4769 35 : ret = tevent_loop_once(ev);
4770 35 : if (ret == -1) {
4771 0 : printf("tevent_loop_once failed: %s\n",
4772 0 : strerror(errno));
4773 0 : return false;
4774 : }
4775 : }
4776 :
4777 5 : status = cli_close(cli2, fnum2);
4778 5 : if (!NT_STATUS_IS_OK(status)) {
4779 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4780 0 : correct = false;
4781 : }
4782 :
4783 5 : status = cli_close(cli1, fnum1);
4784 5 : if (!NT_STATUS_IS_OK(status)) {
4785 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4786 0 : correct = false;
4787 : }
4788 :
4789 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4790 5 : if (!NT_STATUS_IS_OK(status)) {
4791 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4792 0 : correct = false;
4793 : }
4794 :
4795 5 : status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4796 5 : if (!NT_STATUS_IS_OK(status)) {
4797 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4798 0 : correct = false;
4799 : }
4800 :
4801 5 : if (!torture_close_connection(cli1)) {
4802 0 : correct = false;
4803 : }
4804 :
4805 5 : if (!got_break) {
4806 0 : correct = false;
4807 : }
4808 :
4809 5 : printf("finished oplock test 4\n");
4810 :
4811 5 : return correct;
4812 : }
4813 :
4814 5 : static void oplock4_got_break(struct tevent_req *req)
4815 : {
4816 5 : struct oplock4_state *state = tevent_req_callback_data(
4817 : req, struct oplock4_state);
4818 : uint16_t fnum;
4819 : uint8_t level;
4820 : NTSTATUS status;
4821 :
4822 5 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4823 5 : TALLOC_FREE(req);
4824 5 : if (!NT_STATUS_IS_OK(status)) {
4825 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4826 : nt_errstr(status));
4827 0 : return;
4828 : }
4829 5 : *state->got_break = true;
4830 :
4831 5 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
4832 : NO_OPLOCK);
4833 5 : if (req == NULL) {
4834 0 : printf("cli_oplock_ack_send failed\n");
4835 0 : return;
4836 : }
4837 : }
4838 :
4839 5 : static void oplock4_got_open(struct tevent_req *req)
4840 : {
4841 5 : struct oplock4_state *state = tevent_req_callback_data(
4842 : req, struct oplock4_state);
4843 : NTSTATUS status;
4844 :
4845 5 : status = cli_openx_recv(req, state->fnum2);
4846 5 : if (!NT_STATUS_IS_OK(status)) {
4847 0 : printf("cli_openx_recv returned %s\n", nt_errstr(status));
4848 0 : *state->fnum2 = 0xffff;
4849 : }
4850 5 : }
4851 :
4852 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
4853 :
4854 : struct oplock5_state {
4855 : int pipe_down_fd;
4856 : };
4857 :
4858 : /*
4859 : * Async open the file that has a kernel oplock, do an echo to get
4860 : * that 100% across, close the file to signal to the child fd that the
4861 : * oplock can be dropped, wait for the open reply.
4862 : */
4863 :
4864 : static void oplock5_opened(struct tevent_req *subreq);
4865 : static void oplock5_pong(struct tevent_req *subreq);
4866 : static void oplock5_timedout(struct tevent_req *subreq);
4867 :
4868 1 : static struct tevent_req *oplock5_send(
4869 : TALLOC_CTX *mem_ctx,
4870 : struct tevent_context *ev,
4871 : struct cli_state *cli,
4872 : const char *fname,
4873 : int pipe_down_fd)
4874 : {
4875 1 : struct tevent_req *req = NULL, *subreq = NULL;
4876 1 : struct oplock5_state *state = NULL;
4877 : static uint8_t data = 0;
4878 :
4879 1 : req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
4880 1 : if (req == NULL) {
4881 0 : return NULL;
4882 : }
4883 1 : state->pipe_down_fd = pipe_down_fd;
4884 :
4885 1 : subreq = cli_ntcreate_send(
4886 : state,
4887 : ev,
4888 : cli,
4889 : fname,
4890 : 0, /* CreatFlags */
4891 : SEC_FILE_READ_DATA, /* DesiredAccess */
4892 : FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
4893 : FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
4894 : FILE_OPEN, /* CreateDisposition */
4895 : FILE_NON_DIRECTORY_FILE, /* CreateOptions */
4896 : 0, /* Impersonation */
4897 : 0); /* SecurityFlags */
4898 1 : if (tevent_req_nomem(subreq, req)) {
4899 0 : return tevent_req_post(req, ev);
4900 : }
4901 1 : tevent_req_set_callback(subreq, oplock5_opened, req);
4902 :
4903 1 : subreq = cli_echo_send(
4904 : state,
4905 : ev,
4906 : cli,
4907 : 1,
4908 1 : (DATA_BLOB) { .data = &data, .length = sizeof(data) });
4909 1 : if (tevent_req_nomem(subreq, req)) {
4910 0 : return tevent_req_post(req, ev);
4911 : }
4912 1 : tevent_req_set_callback(subreq, oplock5_pong, req);
4913 :
4914 1 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
4915 1 : if (tevent_req_nomem(subreq, req)) {
4916 0 : return tevent_req_post(req, ev);
4917 : }
4918 1 : tevent_req_set_callback(subreq, oplock5_timedout, req);
4919 :
4920 1 : return req;
4921 : }
4922 :
4923 1 : static void oplock5_opened(struct tevent_req *subreq)
4924 : {
4925 1 : struct tevent_req *req = tevent_req_callback_data(
4926 : subreq, struct tevent_req);
4927 : NTSTATUS status;
4928 : uint16_t fnum;
4929 :
4930 1 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
4931 1 : TALLOC_FREE(subreq);
4932 1 : if (tevent_req_nterror(req, status)) {
4933 0 : return;
4934 : }
4935 1 : tevent_req_done(req);
4936 : }
4937 :
4938 1 : static void oplock5_pong(struct tevent_req *subreq)
4939 : {
4940 1 : struct tevent_req *req = tevent_req_callback_data(
4941 : subreq, struct tevent_req);
4942 1 : struct oplock5_state *state = tevent_req_data(
4943 : req, struct oplock5_state);
4944 : NTSTATUS status;
4945 :
4946 1 : status = cli_echo_recv(subreq);
4947 1 : TALLOC_FREE(subreq);
4948 1 : if (tevent_req_nterror(req, status)) {
4949 0 : return;
4950 : }
4951 :
4952 1 : close(state->pipe_down_fd);
4953 : }
4954 :
4955 0 : static void oplock5_timedout(struct tevent_req *subreq)
4956 : {
4957 0 : struct tevent_req *req = tevent_req_callback_data(
4958 : subreq, struct tevent_req);
4959 : bool ok;
4960 :
4961 0 : ok = tevent_wakeup_recv(subreq);
4962 0 : TALLOC_FREE(subreq);
4963 0 : if (!ok) {
4964 0 : tevent_req_oom(req);
4965 0 : return;
4966 : }
4967 0 : tevent_req_nterror(req, NT_STATUS_TIMEOUT);
4968 : }
4969 :
4970 1 : static NTSTATUS oplock5_recv(struct tevent_req *req)
4971 : {
4972 1 : return tevent_req_simple_recv_ntstatus(req);
4973 : }
4974 :
4975 1 : static bool run_oplock5(int dummy)
4976 : {
4977 1 : struct tevent_context *ev = NULL;
4978 1 : struct tevent_req *req = NULL;
4979 1 : struct cli_state *cli = NULL;
4980 1 : const char *fname = "oplock5.txt";
4981 : int pipe_down[2], pipe_up[2];
4982 : pid_t child_pid;
4983 1 : uint8_t c = '\0';
4984 : NTSTATUS status;
4985 : int ret;
4986 : bool ok;
4987 :
4988 1 : printf("starting oplock5\n");
4989 :
4990 1 : if (local_path == NULL) {
4991 0 : d_fprintf(stderr, "oplock5 must be given a local path via "
4992 : "-l <localpath>\n");
4993 0 : return false;
4994 : }
4995 :
4996 1 : ret = pipe(pipe_down);
4997 1 : if (ret == -1) {
4998 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4999 0 : return false;
5000 : }
5001 1 : ret = pipe(pipe_up);
5002 1 : if (ret == -1) {
5003 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5004 0 : return false;
5005 : }
5006 :
5007 1 : child_pid = fork();
5008 2 : if (child_pid == -1) {
5009 0 : d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5010 0 : return false;
5011 : }
5012 :
5013 2 : if (child_pid == 0) {
5014 1 : char *local_file = NULL;
5015 : int fd;
5016 :
5017 1 : close(pipe_down[1]);
5018 1 : close(pipe_up[0]);
5019 :
5020 2 : local_file = talloc_asprintf(
5021 1 : talloc_tos(), "%s/%s", local_path, fname);
5022 1 : if (local_file == 0) {
5023 0 : c = 1;
5024 0 : goto do_write;
5025 : }
5026 1 : fd = open(local_file, O_RDWR|O_CREAT, 0644);
5027 1 : if (fd == -1) {
5028 0 : d_fprintf(stderr,
5029 : "open(%s) in child failed: %s\n",
5030 : local_file,
5031 0 : strerror(errno));
5032 0 : c = 2;
5033 0 : goto do_write;
5034 : }
5035 :
5036 1 : signal(SIGIO, SIG_IGN);
5037 :
5038 1 : ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5039 1 : if (ret == -1) {
5040 0 : d_fprintf(stderr,
5041 : "SETLEASE in child failed: %s\n",
5042 0 : strerror(errno));
5043 0 : c = 3;
5044 0 : goto do_write;
5045 : }
5046 :
5047 2 : do_write:
5048 1 : ret = sys_write(pipe_up[1], &c, sizeof(c));
5049 1 : if (ret == -1) {
5050 0 : d_fprintf(stderr,
5051 : "sys_write failed: %s\n",
5052 0 : strerror(errno));
5053 0 : exit(4);
5054 : }
5055 1 : ret = sys_read(pipe_down[0], &c, sizeof(c));
5056 1 : if (ret == -1) {
5057 0 : d_fprintf(stderr,
5058 : "sys_read failed: %s\n",
5059 0 : strerror(errno));
5060 0 : exit(5);
5061 : }
5062 1 : exit(0);
5063 : }
5064 :
5065 1 : close(pipe_up[1]);
5066 1 : close(pipe_down[0]);
5067 :
5068 1 : ret = sys_read(pipe_up[0], &c, sizeof(c));
5069 1 : if (ret != 1) {
5070 0 : d_fprintf(stderr,
5071 : "sys_read failed: %s\n",
5072 0 : strerror(errno));
5073 0 : return false;
5074 : }
5075 1 : if (c != 0) {
5076 0 : d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5077 0 : return false;
5078 : }
5079 :
5080 1 : ok = torture_open_connection(&cli, 0);
5081 1 : if (!ok) {
5082 0 : d_fprintf(stderr, "torture_open_connection failed\n");
5083 0 : return false;
5084 : }
5085 :
5086 1 : ev = samba_tevent_context_init(talloc_tos());
5087 1 : if (ev == NULL) {
5088 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
5089 0 : return false;
5090 : }
5091 :
5092 1 : req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5093 1 : if (req == NULL) {
5094 0 : d_fprintf(stderr, "oplock5_send failed\n");
5095 0 : return false;
5096 : }
5097 :
5098 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
5099 1 : if (!ok) {
5100 0 : d_fprintf(stderr,
5101 : "tevent_req_poll_ntstatus failed: %s\n",
5102 : nt_errstr(status));
5103 0 : return false;
5104 : }
5105 :
5106 1 : status = oplock5_recv(req);
5107 1 : TALLOC_FREE(req);
5108 1 : if (!NT_STATUS_IS_OK(status)) {
5109 0 : d_fprintf(stderr,
5110 : "oplock5 failed: %s\n",
5111 : nt_errstr(status));
5112 0 : return false;
5113 : }
5114 :
5115 1 : return true;
5116 : }
5117 :
5118 : #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5119 :
5120 : /*
5121 : Test delete on close semantics.
5122 : */
5123 5 : static bool run_deletetest(int dummy)
5124 : {
5125 5 : struct cli_state *cli1 = NULL;
5126 5 : struct cli_state *cli2 = NULL;
5127 5 : const char *fname = "\\delete.file";
5128 5 : uint16_t fnum1 = (uint16_t)-1;
5129 5 : uint16_t fnum2 = (uint16_t)-1;
5130 5 : bool correct = false;
5131 : NTSTATUS status;
5132 :
5133 5 : printf("starting delete test\n");
5134 :
5135 5 : if (!torture_open_connection(&cli1, 0)) {
5136 0 : return False;
5137 : }
5138 :
5139 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5140 :
5141 : /* Test 1 - this should delete the file on close. */
5142 :
5143 5 : cli_setatr(cli1, fname, 0, 0);
5144 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5145 :
5146 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5147 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5148 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5149 5 : if (!NT_STATUS_IS_OK(status)) {
5150 0 : printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5151 0 : goto fail;
5152 : }
5153 :
5154 5 : status = cli_close(cli1, fnum1);
5155 5 : if (!NT_STATUS_IS_OK(status)) {
5156 0 : printf("[1] close failed (%s)\n", nt_errstr(status));
5157 0 : goto fail;
5158 : }
5159 :
5160 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5161 5 : if (NT_STATUS_IS_OK(status)) {
5162 0 : printf("[1] open of %s succeeded (should fail)\n", fname);
5163 0 : goto fail;
5164 : }
5165 :
5166 5 : printf("first delete on close test succeeded.\n");
5167 :
5168 : /* Test 2 - this should delete the file on close. */
5169 :
5170 5 : cli_setatr(cli1, fname, 0, 0);
5171 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5172 :
5173 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5174 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5175 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5176 5 : if (!NT_STATUS_IS_OK(status)) {
5177 0 : printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5178 0 : goto fail;
5179 : }
5180 :
5181 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5182 5 : if (!NT_STATUS_IS_OK(status)) {
5183 0 : printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5184 0 : goto fail;
5185 : }
5186 :
5187 5 : status = cli_close(cli1, fnum1);
5188 5 : if (!NT_STATUS_IS_OK(status)) {
5189 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5190 0 : goto fail;
5191 : }
5192 :
5193 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5194 5 : if (NT_STATUS_IS_OK(status)) {
5195 0 : printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5196 0 : status = cli_close(cli1, fnum1);
5197 0 : if (!NT_STATUS_IS_OK(status)) {
5198 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5199 : }
5200 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5201 0 : goto fail;
5202 : }
5203 :
5204 5 : printf("second delete on close test succeeded.\n");
5205 :
5206 : /* Test 3 - ... */
5207 5 : cli_setatr(cli1, fname, 0, 0);
5208 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5209 :
5210 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5211 : FILE_ATTRIBUTE_NORMAL,
5212 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5213 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5214 5 : if (!NT_STATUS_IS_OK(status)) {
5215 0 : printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5216 0 : goto fail;
5217 : }
5218 :
5219 : /* This should fail with a sharing violation - open for delete is only compatible
5220 : with SHARE_DELETE. */
5221 :
5222 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5223 : FILE_ATTRIBUTE_NORMAL,
5224 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5225 : FILE_OPEN, 0, 0, &fnum2, NULL);
5226 5 : if (NT_STATUS_IS_OK(status)) {
5227 0 : printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5228 0 : goto fail;
5229 : }
5230 :
5231 : /* This should succeed. */
5232 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5233 : FILE_ATTRIBUTE_NORMAL,
5234 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5235 : FILE_OPEN, 0, 0, &fnum2, NULL);
5236 5 : if (!NT_STATUS_IS_OK(status)) {
5237 0 : printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5238 0 : goto fail;
5239 : }
5240 :
5241 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5242 5 : if (!NT_STATUS_IS_OK(status)) {
5243 0 : printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5244 0 : goto fail;
5245 : }
5246 :
5247 5 : status = cli_close(cli1, fnum1);
5248 5 : if (!NT_STATUS_IS_OK(status)) {
5249 0 : printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5250 0 : goto fail;
5251 : }
5252 :
5253 5 : status = cli_close(cli1, fnum2);
5254 5 : if (!NT_STATUS_IS_OK(status)) {
5255 0 : printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5256 0 : goto fail;
5257 : }
5258 :
5259 : /* This should fail - file should no longer be there. */
5260 :
5261 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5262 5 : if (NT_STATUS_IS_OK(status)) {
5263 0 : printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5264 0 : status = cli_close(cli1, fnum1);
5265 0 : if (!NT_STATUS_IS_OK(status)) {
5266 0 : printf("[3] close failed (%s)\n", nt_errstr(status));
5267 : }
5268 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5269 0 : goto fail;
5270 : }
5271 :
5272 5 : printf("third delete on close test succeeded.\n");
5273 :
5274 : /* Test 4 ... */
5275 5 : cli_setatr(cli1, fname, 0, 0);
5276 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5277 :
5278 5 : status = cli_ntcreate(cli1, fname, 0,
5279 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5280 : FILE_ATTRIBUTE_NORMAL,
5281 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5282 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5283 5 : if (!NT_STATUS_IS_OK(status)) {
5284 0 : printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5285 0 : goto fail;
5286 : }
5287 :
5288 : /* This should succeed. */
5289 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5290 : FILE_ATTRIBUTE_NORMAL,
5291 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5292 : FILE_OPEN, 0, 0, &fnum2, NULL);
5293 5 : if (!NT_STATUS_IS_OK(status)) {
5294 0 : printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5295 0 : goto fail;
5296 : }
5297 :
5298 5 : status = cli_close(cli1, fnum2);
5299 5 : if (!NT_STATUS_IS_OK(status)) {
5300 0 : printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5301 0 : goto fail;
5302 : }
5303 :
5304 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5305 5 : if (!NT_STATUS_IS_OK(status)) {
5306 0 : printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5307 0 : goto fail;
5308 : }
5309 :
5310 : /* This should fail - no more opens once delete on close set. */
5311 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5312 : FILE_ATTRIBUTE_NORMAL,
5313 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5314 : FILE_OPEN, 0, 0, &fnum2, NULL);
5315 5 : if (NT_STATUS_IS_OK(status)) {
5316 0 : printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5317 0 : goto fail;
5318 : }
5319 :
5320 5 : status = cli_close(cli1, fnum1);
5321 5 : if (!NT_STATUS_IS_OK(status)) {
5322 0 : printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5323 0 : goto fail;
5324 : }
5325 :
5326 5 : printf("fourth delete on close test succeeded.\n");
5327 :
5328 : /* Test 5 ... */
5329 5 : cli_setatr(cli1, fname, 0, 0);
5330 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5331 :
5332 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5333 5 : if (!NT_STATUS_IS_OK(status)) {
5334 0 : printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5335 0 : goto fail;
5336 : }
5337 :
5338 : /* This should fail - only allowed on NT opens with DELETE access. */
5339 :
5340 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5341 5 : if (NT_STATUS_IS_OK(status)) {
5342 0 : printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5343 0 : goto fail;
5344 : }
5345 :
5346 5 : status = cli_close(cli1, fnum1);
5347 5 : if (!NT_STATUS_IS_OK(status)) {
5348 0 : printf("[5] close failed (%s)\n", nt_errstr(status));
5349 0 : goto fail;
5350 : }
5351 :
5352 5 : printf("fifth delete on close test succeeded.\n");
5353 :
5354 : /* Test 6 ... */
5355 5 : cli_setatr(cli1, fname, 0, 0);
5356 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5357 :
5358 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5359 : FILE_ATTRIBUTE_NORMAL,
5360 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5361 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5362 5 : if (!NT_STATUS_IS_OK(status)) {
5363 0 : printf("[6] open of %s failed (%s)\n", fname,
5364 : nt_errstr(status));
5365 0 : goto fail;
5366 : }
5367 :
5368 : /* This should fail - only allowed on NT opens with DELETE access. */
5369 :
5370 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5371 5 : if (NT_STATUS_IS_OK(status)) {
5372 0 : printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5373 0 : goto fail;
5374 : }
5375 :
5376 5 : status = cli_close(cli1, fnum1);
5377 5 : if (!NT_STATUS_IS_OK(status)) {
5378 0 : printf("[6] close failed (%s)\n", nt_errstr(status));
5379 0 : goto fail;
5380 : }
5381 :
5382 5 : printf("sixth delete on close test succeeded.\n");
5383 :
5384 : /* Test 7 ... */
5385 5 : cli_setatr(cli1, fname, 0, 0);
5386 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5387 :
5388 5 : status = cli_ntcreate(cli1, fname, 0,
5389 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5390 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5391 : 0, 0, &fnum1, NULL);
5392 5 : if (!NT_STATUS_IS_OK(status)) {
5393 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5394 0 : goto fail;
5395 : }
5396 :
5397 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5398 5 : if (!NT_STATUS_IS_OK(status)) {
5399 0 : printf("[7] setting delete_on_close on file failed !\n");
5400 0 : goto fail;
5401 : }
5402 :
5403 5 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5404 5 : if (!NT_STATUS_IS_OK(status)) {
5405 0 : printf("[7] unsetting delete_on_close on file failed !\n");
5406 0 : goto fail;
5407 : }
5408 :
5409 5 : status = cli_close(cli1, fnum1);
5410 5 : if (!NT_STATUS_IS_OK(status)) {
5411 0 : printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5412 0 : goto fail;
5413 : }
5414 :
5415 : /* This next open should succeed - we reset the flag. */
5416 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5417 5 : if (!NT_STATUS_IS_OK(status)) {
5418 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5419 0 : goto fail;
5420 : }
5421 :
5422 5 : status = cli_close(cli1, fnum1);
5423 5 : if (!NT_STATUS_IS_OK(status)) {
5424 0 : printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5425 0 : goto fail;
5426 : }
5427 :
5428 5 : printf("seventh delete on close test succeeded.\n");
5429 :
5430 : /* Test 8 ... */
5431 5 : cli_setatr(cli1, fname, 0, 0);
5432 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5433 :
5434 5 : if (!torture_open_connection(&cli2, 1)) {
5435 0 : printf("[8] failed to open second connection.\n");
5436 0 : goto fail;
5437 : }
5438 :
5439 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5440 :
5441 5 : status = cli_ntcreate(cli1, fname, 0,
5442 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5443 : FILE_ATTRIBUTE_NORMAL,
5444 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5445 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5446 5 : if (!NT_STATUS_IS_OK(status)) {
5447 0 : printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5448 0 : goto fail;
5449 : }
5450 :
5451 5 : status = cli_ntcreate(cli2, fname, 0,
5452 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5453 : FILE_ATTRIBUTE_NORMAL,
5454 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5455 : FILE_OPEN, 0, 0, &fnum2, NULL);
5456 5 : if (!NT_STATUS_IS_OK(status)) {
5457 0 : printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5458 0 : goto fail;
5459 : }
5460 :
5461 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5462 5 : if (!NT_STATUS_IS_OK(status)) {
5463 0 : printf("[8] setting delete_on_close on file failed !\n");
5464 0 : goto fail;
5465 : }
5466 :
5467 5 : status = cli_close(cli1, fnum1);
5468 5 : if (!NT_STATUS_IS_OK(status)) {
5469 0 : printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5470 0 : goto fail;
5471 : }
5472 :
5473 5 : status = cli_close(cli2, fnum2);
5474 5 : if (!NT_STATUS_IS_OK(status)) {
5475 0 : printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5476 0 : goto fail;
5477 : }
5478 :
5479 : /* This should fail.. */
5480 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5481 5 : if (NT_STATUS_IS_OK(status)) {
5482 0 : printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5483 0 : goto fail;
5484 : }
5485 :
5486 5 : printf("eighth delete on close test succeeded.\n");
5487 :
5488 : /* Test 9 ... */
5489 :
5490 : /* This should fail - we need to set DELETE_ACCESS. */
5491 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5492 : FILE_ATTRIBUTE_NORMAL,
5493 : FILE_SHARE_NONE,
5494 : FILE_OVERWRITE_IF,
5495 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5496 5 : if (NT_STATUS_IS_OK(status)) {
5497 0 : printf("[9] open of %s succeeded should have failed!\n", fname);
5498 0 : goto fail;
5499 : }
5500 :
5501 5 : printf("ninth delete on close test succeeded.\n");
5502 :
5503 : /* Test 10 ... */
5504 :
5505 5 : status = cli_ntcreate(cli1, fname, 0,
5506 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5507 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5508 : FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5509 : 0, &fnum1, NULL);
5510 5 : if (!NT_STATUS_IS_OK(status)) {
5511 0 : printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5512 0 : goto fail;
5513 : }
5514 :
5515 : /* This should delete the file. */
5516 5 : status = cli_close(cli1, fnum1);
5517 5 : if (!NT_STATUS_IS_OK(status)) {
5518 0 : printf("[10] close failed (%s)\n", nt_errstr(status));
5519 0 : goto fail;
5520 : }
5521 :
5522 : /* This should fail.. */
5523 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5524 5 : if (NT_STATUS_IS_OK(status)) {
5525 0 : printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5526 0 : goto fail;
5527 : }
5528 :
5529 5 : printf("tenth delete on close test succeeded.\n");
5530 :
5531 : /* Test 11 ... */
5532 :
5533 5 : cli_setatr(cli1, fname, 0, 0);
5534 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5535 :
5536 : /* Can we open a read-only file with delete access? */
5537 :
5538 : /* Create a readonly file. */
5539 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5540 : FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5541 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5542 5 : if (!NT_STATUS_IS_OK(status)) {
5543 0 : printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5544 0 : goto fail;
5545 : }
5546 :
5547 5 : status = cli_close(cli1, fnum1);
5548 5 : if (!NT_STATUS_IS_OK(status)) {
5549 0 : printf("[11] close failed (%s)\n", nt_errstr(status));
5550 0 : goto fail;
5551 : }
5552 :
5553 : /* Now try open for delete access. */
5554 5 : status = cli_ntcreate(cli1, fname, 0,
5555 : FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5556 : 0,
5557 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5558 : FILE_OPEN, 0, 0, &fnum1, NULL);
5559 5 : if (!NT_STATUS_IS_OK(status)) {
5560 0 : printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5561 0 : goto fail;
5562 : }
5563 :
5564 5 : cli_close(cli1, fnum1);
5565 :
5566 5 : printf("eleventh delete on close test succeeded.\n");
5567 :
5568 : /*
5569 : * Test 12
5570 : * like test 4 but with initial delete on close
5571 : */
5572 :
5573 5 : cli_setatr(cli1, fname, 0, 0);
5574 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5575 :
5576 5 : status = cli_ntcreate(cli1, fname, 0,
5577 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5578 : FILE_ATTRIBUTE_NORMAL,
5579 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5580 : FILE_OVERWRITE_IF,
5581 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5582 5 : if (!NT_STATUS_IS_OK(status)) {
5583 0 : printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5584 0 : goto fail;
5585 : }
5586 :
5587 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5588 : FILE_ATTRIBUTE_NORMAL,
5589 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5590 : FILE_OPEN, 0, 0, &fnum2, NULL);
5591 5 : if (!NT_STATUS_IS_OK(status)) {
5592 0 : printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5593 0 : goto fail;
5594 : }
5595 :
5596 5 : status = cli_close(cli1, fnum2);
5597 5 : if (!NT_STATUS_IS_OK(status)) {
5598 0 : printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5599 0 : goto fail;
5600 : }
5601 :
5602 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5603 5 : if (!NT_STATUS_IS_OK(status)) {
5604 0 : printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5605 0 : goto fail;
5606 : }
5607 :
5608 : /* This should fail - no more opens once delete on close set. */
5609 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5610 : FILE_ATTRIBUTE_NORMAL,
5611 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5612 : FILE_OPEN, 0, 0, &fnum2, NULL);
5613 5 : if (NT_STATUS_IS_OK(status)) {
5614 0 : printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5615 0 : goto fail;
5616 : }
5617 :
5618 5 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5619 5 : if (!NT_STATUS_IS_OK(status)) {
5620 0 : printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5621 0 : goto fail;
5622 : }
5623 :
5624 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5625 : FILE_ATTRIBUTE_NORMAL,
5626 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5627 : FILE_OPEN, 0, 0, &fnum2, NULL);
5628 5 : if (!NT_STATUS_IS_OK(status)) {
5629 0 : printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5630 0 : goto fail;
5631 : }
5632 :
5633 5 : status = cli_close(cli1, fnum2);
5634 5 : if (!NT_STATUS_IS_OK(status)) {
5635 0 : printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5636 0 : goto fail;
5637 : }
5638 :
5639 5 : status = cli_close(cli1, fnum1);
5640 5 : if (!NT_STATUS_IS_OK(status)) {
5641 0 : printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5642 0 : goto fail;
5643 : }
5644 :
5645 : /*
5646 : * setting delete on close on the handle does
5647 : * not unset the initial delete on close...
5648 : */
5649 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5650 : FILE_ATTRIBUTE_NORMAL,
5651 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5652 : FILE_OPEN, 0, 0, &fnum2, NULL);
5653 5 : if (NT_STATUS_IS_OK(status)) {
5654 0 : printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5655 0 : goto fail;
5656 5 : } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5657 0 : printf("ntcreate returned %s, expected "
5658 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5659 : nt_errstr(status));
5660 0 : goto fail;
5661 : }
5662 :
5663 5 : printf("twelfth delete on close test succeeded.\n");
5664 :
5665 :
5666 5 : printf("finished delete test\n");
5667 :
5668 5 : correct = true;
5669 :
5670 5 : fail:
5671 : /* FIXME: This will crash if we aborted before cli2 got
5672 : * intialized, because these functions don't handle
5673 : * uninitialized connections. */
5674 :
5675 5 : if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5676 5 : if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5677 5 : cli_setatr(cli1, fname, 0, 0);
5678 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5679 :
5680 5 : if (cli1 && !torture_close_connection(cli1)) {
5681 0 : correct = False;
5682 : }
5683 5 : if (cli2 && !torture_close_connection(cli2)) {
5684 0 : correct = False;
5685 : }
5686 5 : return correct;
5687 : }
5688 :
5689 : struct delete_stream_state {
5690 : bool closed;
5691 : };
5692 :
5693 : static void delete_stream_unlinked(struct tevent_req *subreq);
5694 : static void delete_stream_closed(struct tevent_req *subreq);
5695 :
5696 5 : static struct tevent_req *delete_stream_send(
5697 : TALLOC_CTX *mem_ctx,
5698 : struct tevent_context *ev,
5699 : struct cli_state *cli,
5700 : const char *base_fname,
5701 : uint16_t stream_fnum)
5702 : {
5703 5 : struct tevent_req *req = NULL, *subreq = NULL;
5704 5 : struct delete_stream_state *state = NULL;
5705 :
5706 5 : req = tevent_req_create(
5707 : mem_ctx, &state, struct delete_stream_state);
5708 5 : if (req == NULL) {
5709 0 : return NULL;
5710 : }
5711 :
5712 5 : subreq = cli_unlink_send(
5713 : state,
5714 : ev,
5715 : cli,
5716 : base_fname,
5717 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5718 5 : if (tevent_req_nomem(subreq, req)) {
5719 0 : return tevent_req_post(req, ev);
5720 : }
5721 5 : tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5722 :
5723 5 : subreq = cli_close_send(state, ev, cli, stream_fnum);
5724 5 : if (tevent_req_nomem(subreq, req)) {
5725 0 : return tevent_req_post(req, ev);
5726 : }
5727 5 : tevent_req_set_callback(subreq, delete_stream_closed, req);
5728 :
5729 5 : return req;
5730 : }
5731 :
5732 5 : static void delete_stream_unlinked(struct tevent_req *subreq)
5733 : {
5734 5 : struct tevent_req *req = tevent_req_callback_data(
5735 : subreq, struct tevent_req);
5736 5 : struct delete_stream_state *state = tevent_req_data(
5737 : req, struct delete_stream_state);
5738 : NTSTATUS status;
5739 :
5740 5 : status = cli_unlink_recv(subreq);
5741 5 : TALLOC_FREE(subreq);
5742 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5743 0 : printf("cli_unlink returned %s\n",
5744 : nt_errstr(status));
5745 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5746 0 : return;
5747 : }
5748 5 : if (!state->closed) {
5749 : /* close reply should have come in first */
5750 0 : printf("Not closed\n");
5751 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5752 0 : return;
5753 : }
5754 5 : tevent_req_done(req);
5755 : }
5756 :
5757 5 : static void delete_stream_closed(struct tevent_req *subreq)
5758 : {
5759 5 : struct tevent_req *req = tevent_req_callback_data(
5760 : subreq, struct tevent_req);
5761 5 : struct delete_stream_state *state = tevent_req_data(
5762 : req, struct delete_stream_state);
5763 : NTSTATUS status;
5764 :
5765 5 : status = cli_close_recv(subreq);
5766 5 : TALLOC_FREE(subreq);
5767 5 : if (tevent_req_nterror(req, status)) {
5768 0 : return;
5769 : }
5770 : /* also waiting for the unlink to come back */
5771 5 : state->closed = true;
5772 : }
5773 :
5774 5 : static NTSTATUS delete_stream_recv(struct tevent_req *req)
5775 : {
5776 5 : return tevent_req_simple_recv_ntstatus(req);
5777 : }
5778 :
5779 5 : static bool run_delete_stream(int dummy)
5780 : {
5781 5 : struct tevent_context *ev = NULL;
5782 5 : struct tevent_req *req = NULL;
5783 5 : struct cli_state *cli = NULL;
5784 5 : const char fname[] = "delete_stream";
5785 5 : const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5786 : uint16_t fnum1, fnum2;
5787 : NTSTATUS status;
5788 : bool ok;
5789 :
5790 5 : printf("Starting stream delete test\n");
5791 :
5792 5 : ok = torture_open_connection(&cli, 0);
5793 5 : if (!ok) {
5794 0 : return false;
5795 : }
5796 :
5797 5 : cli_setatr(cli, fname, 0, 0);
5798 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5799 :
5800 : /* Create the file. */
5801 5 : status = cli_ntcreate(
5802 : cli,
5803 : fname,
5804 : 0,
5805 : READ_CONTROL_ACCESS,
5806 : 0,
5807 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5808 : FILE_CREATE,
5809 : 0x0,
5810 : 0x0,
5811 : &fnum1,
5812 : NULL);
5813 5 : if (!NT_STATUS_IS_OK(status)) {
5814 0 : d_fprintf(stderr,
5815 : "cli_ntcreate of %s failed (%s)\n",
5816 : fname,
5817 : nt_errstr(status));
5818 0 : return false;
5819 : }
5820 5 : status = cli_close(cli, fnum1);
5821 5 : if (!NT_STATUS_IS_OK(status)) {
5822 0 : d_fprintf(stderr,
5823 : "cli_close of %s failed (%s)\n",
5824 : fname,
5825 : nt_errstr(status));
5826 0 : return false;
5827 : }
5828 :
5829 : /* Now create the stream. */
5830 5 : status = cli_ntcreate(
5831 : cli,
5832 : fname_stream,
5833 : 0,
5834 : FILE_WRITE_DATA,
5835 : 0,
5836 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5837 : FILE_CREATE,
5838 : 0x0,
5839 : 0x0,
5840 : &fnum1,
5841 : NULL);
5842 :
5843 5 : if (!NT_STATUS_IS_OK(status)) {
5844 0 : d_fprintf(stderr,
5845 : "cli_ntcreate of %s failed (%s)\n",
5846 : fname_stream,
5847 : nt_errstr(status));
5848 0 : return false;
5849 : }
5850 :
5851 : /* open it a second time */
5852 :
5853 5 : status = cli_ntcreate(
5854 : cli,
5855 : fname_stream,
5856 : 0,
5857 : FILE_WRITE_DATA,
5858 : 0,
5859 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5860 : FILE_OPEN,
5861 : 0x0,
5862 : 0x0,
5863 : &fnum2,
5864 : NULL);
5865 :
5866 5 : if (!NT_STATUS_IS_OK(status)) {
5867 0 : d_fprintf(stderr,
5868 : "2nd cli_ntcreate of %s failed (%s)\n",
5869 : fname_stream,
5870 : nt_errstr(status));
5871 0 : return false;
5872 : }
5873 :
5874 5 : ev = samba_tevent_context_init(talloc_tos());
5875 5 : if (ev == NULL) {
5876 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
5877 0 : return false;
5878 : }
5879 :
5880 5 : req = delete_stream_send(ev, ev, cli, fname, fnum1);
5881 5 : if (req == NULL) {
5882 0 : d_fprintf(stderr, "delete_stream_send failed\n");
5883 0 : return false;
5884 : }
5885 :
5886 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
5887 5 : if (!ok) {
5888 0 : d_fprintf(stderr,
5889 : "tevent_req_poll_ntstatus failed: %s\n",
5890 : nt_errstr(status));
5891 0 : return false;
5892 : }
5893 :
5894 5 : status = delete_stream_recv(req);
5895 5 : TALLOC_FREE(req);
5896 5 : if (!NT_STATUS_IS_OK(status)) {
5897 0 : d_fprintf(stderr,
5898 : "delete_stream failed: %s\n",
5899 : nt_errstr(status));
5900 0 : return false;
5901 : }
5902 :
5903 5 : status = cli_close(cli, fnum2);
5904 5 : if (!NT_STATUS_IS_OK(status)) {
5905 0 : d_fprintf(stderr,
5906 : "close failed: %s\n",
5907 : nt_errstr(status));
5908 0 : return false;
5909 : }
5910 :
5911 5 : status = cli_unlink(
5912 : cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5913 5 : if (!NT_STATUS_IS_OK(status)) {
5914 0 : d_fprintf(stderr,
5915 : "unlink failed: %s\n",
5916 : nt_errstr(status));
5917 0 : return false;
5918 : }
5919 :
5920 5 : return true;
5921 : }
5922 :
5923 : /*
5924 : Exercise delete on close semantics - use on the PRINT1 share in torture
5925 : testing.
5926 : */
5927 2 : static bool run_delete_print_test(int dummy)
5928 : {
5929 2 : struct cli_state *cli1 = NULL;
5930 2 : const char *fname = "print_delete.file";
5931 2 : uint16_t fnum1 = (uint16_t)-1;
5932 2 : bool correct = false;
5933 2 : const char *buf = "print file data\n";
5934 : NTSTATUS status;
5935 :
5936 2 : printf("starting print delete test\n");
5937 :
5938 2 : if (!torture_open_connection(&cli1, 0)) {
5939 0 : return false;
5940 : }
5941 :
5942 2 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5943 :
5944 2 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5945 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5946 : 0, 0, &fnum1, NULL);
5947 2 : if (!NT_STATUS_IS_OK(status)) {
5948 0 : printf("open of %s failed (%s)\n",
5949 : fname,
5950 : nt_errstr(status));
5951 0 : goto fail;
5952 : }
5953 :
5954 2 : status = cli_writeall(cli1,
5955 : fnum1,
5956 : 0,
5957 : (const uint8_t *)buf,
5958 : 0, /* offset */
5959 : strlen(buf), /* size */
5960 : NULL);
5961 2 : if (!NT_STATUS_IS_OK(status)) {
5962 0 : printf("writing print file data failed (%s)\n",
5963 : nt_errstr(status));
5964 0 : goto fail;
5965 : }
5966 :
5967 2 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5968 2 : if (!NT_STATUS_IS_OK(status)) {
5969 0 : printf("setting delete_on_close failed (%s)\n",
5970 : nt_errstr(status));
5971 0 : goto fail;
5972 : }
5973 :
5974 2 : status = cli_close(cli1, fnum1);
5975 2 : if (!NT_STATUS_IS_OK(status)) {
5976 0 : printf("close failed (%s)\n", nt_errstr(status));
5977 0 : goto fail;
5978 : }
5979 :
5980 2 : printf("finished print delete test\n");
5981 :
5982 2 : correct = true;
5983 :
5984 2 : fail:
5985 :
5986 2 : if (fnum1 != (uint16_t)-1) {
5987 2 : cli_close(cli1, fnum1);
5988 : }
5989 :
5990 2 : if (cli1 && !torture_close_connection(cli1)) {
5991 0 : correct = false;
5992 : }
5993 2 : return correct;
5994 : }
5995 :
5996 : /*
5997 : Test wildcard delete.
5998 : */
5999 5 : static bool run_wild_deletetest(int dummy)
6000 : {
6001 5 : struct cli_state *cli = NULL;
6002 5 : const char *dname = "\\WTEST";
6003 5 : const char *fname = "\\WTEST\\A";
6004 5 : const char *wunlink_name = "\\WTEST\\*";
6005 5 : uint16_t fnum1 = (uint16_t)-1;
6006 5 : bool correct = false;
6007 : NTSTATUS status;
6008 :
6009 5 : printf("starting wildcard delete test\n");
6010 :
6011 5 : if (!torture_open_connection(&cli, 0)) {
6012 0 : return false;
6013 : }
6014 :
6015 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6016 :
6017 5 : cli_unlink(cli, fname, 0);
6018 5 : cli_rmdir(cli, dname);
6019 5 : status = cli_mkdir(cli, dname);
6020 5 : if (!NT_STATUS_IS_OK(status)) {
6021 0 : printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
6022 0 : goto fail;
6023 : }
6024 5 : status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
6025 5 : if (!NT_STATUS_IS_OK(status)) {
6026 0 : printf("open of %s failed %s!\n", fname, nt_errstr(status));
6027 0 : goto fail;
6028 : }
6029 5 : status = cli_close(cli, fnum1);
6030 5 : fnum1 = -1;
6031 :
6032 : /*
6033 : * Note the unlink attribute-type of zero. This should
6034 : * map into FILE_ATTRIBUTE_NORMAL at the server even
6035 : * on a wildcard delete.
6036 : */
6037 :
6038 5 : status = cli_unlink(cli, wunlink_name, 0);
6039 5 : if (!NT_STATUS_IS_OK(status)) {
6040 0 : printf("unlink of %s failed %s!\n",
6041 : wunlink_name, nt_errstr(status));
6042 0 : goto fail;
6043 : }
6044 :
6045 5 : printf("finished wildcard delete test\n");
6046 :
6047 5 : correct = true;
6048 :
6049 5 : fail:
6050 :
6051 5 : if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
6052 5 : cli_unlink(cli, fname, 0);
6053 5 : cli_rmdir(cli, dname);
6054 :
6055 5 : if (cli && !torture_close_connection(cli)) {
6056 0 : correct = false;
6057 : }
6058 5 : return correct;
6059 : }
6060 :
6061 4 : static bool run_deletetest_ln(int dummy)
6062 : {
6063 : struct cli_state *cli;
6064 4 : const char *fname = "\\delete1";
6065 4 : const char *fname_ln = "\\delete1_ln";
6066 : uint16_t fnum;
6067 : uint16_t fnum1;
6068 : NTSTATUS status;
6069 4 : bool correct = true;
6070 : time_t t;
6071 :
6072 4 : printf("starting deletetest-ln\n");
6073 :
6074 4 : if (!torture_open_connection(&cli, 0)) {
6075 0 : return false;
6076 : }
6077 :
6078 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6079 4 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6080 :
6081 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6082 :
6083 : /* Create the file. */
6084 4 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6085 4 : if (!NT_STATUS_IS_OK(status)) {
6086 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6087 0 : return false;
6088 : }
6089 :
6090 4 : status = cli_close(cli, fnum);
6091 4 : if (!NT_STATUS_IS_OK(status)) {
6092 0 : printf("close1 failed (%s)\n", nt_errstr(status));
6093 0 : return false;
6094 : }
6095 :
6096 : /* Now create a hardlink. */
6097 4 : status = cli_hardlink(cli, fname, fname_ln);
6098 4 : if (!NT_STATUS_IS_OK(status)) {
6099 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
6100 0 : return false;
6101 : }
6102 :
6103 : /* Open the original file. */
6104 4 : status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6105 : FILE_ATTRIBUTE_NORMAL,
6106 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6107 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
6108 4 : if (!NT_STATUS_IS_OK(status)) {
6109 0 : printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6110 0 : return false;
6111 : }
6112 :
6113 : /* Unlink the hard link path. */
6114 4 : status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6115 : FILE_ATTRIBUTE_NORMAL,
6116 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6117 : FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6118 4 : if (!NT_STATUS_IS_OK(status)) {
6119 0 : printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6120 0 : return false;
6121 : }
6122 4 : status = cli_nt_delete_on_close(cli, fnum1, true);
6123 4 : if (!NT_STATUS_IS_OK(status)) {
6124 0 : d_printf("(%s) failed to set delete_on_close %s: %s\n",
6125 : __location__, fname_ln, nt_errstr(status));
6126 0 : return false;
6127 : }
6128 :
6129 4 : status = cli_close(cli, fnum1);
6130 4 : if (!NT_STATUS_IS_OK(status)) {
6131 0 : printf("close %s failed (%s)\n",
6132 : fname_ln, nt_errstr(status));
6133 0 : return false;
6134 : }
6135 :
6136 4 : status = cli_close(cli, fnum);
6137 4 : if (!NT_STATUS_IS_OK(status)) {
6138 0 : printf("close %s failed (%s)\n",
6139 : fname, nt_errstr(status));
6140 0 : return false;
6141 : }
6142 :
6143 : /* Ensure the original file is still there. */
6144 4 : status = cli_getatr(cli, fname, NULL, NULL, &t);
6145 4 : if (!NT_STATUS_IS_OK(status)) {
6146 0 : printf("%s getatr on file %s failed (%s)\n",
6147 : __location__,
6148 : fname,
6149 : nt_errstr(status));
6150 0 : correct = False;
6151 : }
6152 :
6153 : /* Ensure the link path is gone. */
6154 4 : status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6155 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6156 0 : printf("%s, getatr for file %s returned wrong error code %s "
6157 : "- should have been deleted\n",
6158 : __location__,
6159 : fname_ln, nt_errstr(status));
6160 0 : correct = False;
6161 : }
6162 :
6163 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6164 4 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6165 :
6166 4 : if (!torture_close_connection(cli)) {
6167 0 : correct = false;
6168 : }
6169 :
6170 4 : printf("finished deletetest-ln\n");
6171 :
6172 4 : return correct;
6173 : }
6174 :
6175 : /*
6176 : print out server properties
6177 : */
6178 5 : static bool run_properties(int dummy)
6179 : {
6180 : struct cli_state *cli;
6181 5 : bool correct = True;
6182 :
6183 5 : printf("starting properties test\n");
6184 :
6185 5 : ZERO_STRUCT(cli);
6186 :
6187 5 : if (!torture_open_connection(&cli, 0)) {
6188 0 : return False;
6189 : }
6190 :
6191 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6192 :
6193 5 : d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6194 :
6195 5 : if (!torture_close_connection(cli)) {
6196 0 : correct = False;
6197 : }
6198 :
6199 5 : return correct;
6200 : }
6201 :
6202 :
6203 :
6204 : /* FIRST_DESIRED_ACCESS 0xf019f */
6205 : #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6206 : FILE_READ_EA| /* 0xf */ \
6207 : FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6208 : FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6209 : DELETE_ACCESS|READ_CONTROL_ACCESS|\
6210 : WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6211 : /* SECOND_DESIRED_ACCESS 0xe0080 */
6212 : #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6213 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6214 : WRITE_OWNER_ACCESS /* 0xe0000 */
6215 :
6216 : #if 0
6217 : #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6218 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6219 : FILE_READ_DATA|\
6220 : WRITE_OWNER_ACCESS /* */
6221 : #endif
6222 :
6223 : /*
6224 : Test ntcreate calls made by xcopy
6225 : */
6226 5 : static bool run_xcopy(int dummy)
6227 : {
6228 : static struct cli_state *cli1;
6229 5 : const char *fname = "\\test.txt";
6230 5 : bool correct = True;
6231 : uint16_t fnum1, fnum2;
6232 : NTSTATUS status;
6233 :
6234 5 : printf("starting xcopy test\n");
6235 :
6236 5 : if (!torture_open_connection(&cli1, 0)) {
6237 0 : return False;
6238 : }
6239 :
6240 5 : status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6241 : FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6242 : FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6243 5 : if (!NT_STATUS_IS_OK(status)) {
6244 0 : printf("First open failed - %s\n", nt_errstr(status));
6245 0 : return False;
6246 : }
6247 :
6248 5 : status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6249 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6250 : FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6251 5 : if (!NT_STATUS_IS_OK(status)) {
6252 0 : printf("second open failed - %s\n", nt_errstr(status));
6253 0 : return False;
6254 : }
6255 :
6256 5 : if (!torture_close_connection(cli1)) {
6257 0 : correct = False;
6258 : }
6259 :
6260 5 : return correct;
6261 : }
6262 :
6263 : /*
6264 : Test rename on files open with share delete and no share delete.
6265 : */
6266 5 : static bool run_rename(int dummy)
6267 : {
6268 : static struct cli_state *cli1;
6269 5 : const char *fname = "\\test.txt";
6270 5 : const char *fname1 = "\\test1.txt";
6271 5 : bool correct = True;
6272 : uint16_t fnum1;
6273 : uint32_t attr;
6274 : NTSTATUS status;
6275 :
6276 5 : printf("starting rename test\n");
6277 :
6278 5 : if (!torture_open_connection(&cli1, 0)) {
6279 0 : return False;
6280 : }
6281 :
6282 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6283 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6284 :
6285 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6286 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6287 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6288 5 : if (!NT_STATUS_IS_OK(status)) {
6289 0 : printf("First open failed - %s\n", nt_errstr(status));
6290 0 : return False;
6291 : }
6292 :
6293 5 : status = cli_rename(cli1, fname, fname1, false);
6294 5 : if (!NT_STATUS_IS_OK(status)) {
6295 5 : printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6296 : } else {
6297 0 : printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6298 0 : correct = False;
6299 : }
6300 :
6301 5 : status = cli_close(cli1, fnum1);
6302 5 : if (!NT_STATUS_IS_OK(status)) {
6303 0 : printf("close - 1 failed (%s)\n", nt_errstr(status));
6304 0 : return False;
6305 : }
6306 :
6307 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6308 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6309 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6310 : #if 0
6311 : FILE_SHARE_DELETE|FILE_SHARE_NONE,
6312 : #else
6313 : FILE_SHARE_DELETE|FILE_SHARE_READ,
6314 : #endif
6315 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6316 5 : if (!NT_STATUS_IS_OK(status)) {
6317 0 : printf("Second open failed - %s\n", nt_errstr(status));
6318 0 : return False;
6319 : }
6320 :
6321 5 : status = cli_rename(cli1, fname, fname1, false);
6322 5 : if (!NT_STATUS_IS_OK(status)) {
6323 0 : printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6324 0 : correct = False;
6325 : } else {
6326 5 : printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6327 : }
6328 :
6329 5 : status = cli_close(cli1, fnum1);
6330 5 : if (!NT_STATUS_IS_OK(status)) {
6331 0 : printf("close - 2 failed (%s)\n", nt_errstr(status));
6332 0 : return False;
6333 : }
6334 :
6335 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6336 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6337 :
6338 5 : status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6339 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6340 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6341 5 : if (!NT_STATUS_IS_OK(status)) {
6342 0 : printf("Third open failed - %s\n", nt_errstr(status));
6343 0 : return False;
6344 : }
6345 :
6346 :
6347 5 : status = cli_rename(cli1, fname, fname1, false);
6348 5 : if (!NT_STATUS_IS_OK(status)) {
6349 0 : printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6350 0 : correct = False;
6351 : } else {
6352 5 : printf("Third rename succeeded (SHARE_NONE)\n");
6353 : }
6354 :
6355 5 : status = cli_close(cli1, fnum1);
6356 5 : if (!NT_STATUS_IS_OK(status)) {
6357 0 : printf("close - 3 failed (%s)\n", nt_errstr(status));
6358 0 : return False;
6359 : }
6360 :
6361 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6362 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6363 :
6364 : /*----*/
6365 :
6366 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6367 : FILE_ATTRIBUTE_NORMAL,
6368 : FILE_SHARE_READ | FILE_SHARE_WRITE,
6369 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6370 5 : if (!NT_STATUS_IS_OK(status)) {
6371 0 : printf("Fourth open failed - %s\n", nt_errstr(status));
6372 0 : return False;
6373 : }
6374 :
6375 5 : status = cli_rename(cli1, fname, fname1, false);
6376 5 : if (!NT_STATUS_IS_OK(status)) {
6377 5 : printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6378 : } else {
6379 0 : printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6380 0 : correct = False;
6381 : }
6382 :
6383 5 : status = cli_close(cli1, fnum1);
6384 5 : if (!NT_STATUS_IS_OK(status)) {
6385 0 : printf("close - 4 failed (%s)\n", nt_errstr(status));
6386 0 : return False;
6387 : }
6388 :
6389 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6390 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6391 :
6392 : /*--*/
6393 :
6394 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6395 : FILE_ATTRIBUTE_NORMAL,
6396 : FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6397 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6398 5 : if (!NT_STATUS_IS_OK(status)) {
6399 0 : printf("Fifth open failed - %s\n", nt_errstr(status));
6400 0 : return False;
6401 : }
6402 :
6403 5 : status = cli_rename(cli1, fname, fname1, false);
6404 5 : if (!NT_STATUS_IS_OK(status)) {
6405 0 : printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6406 0 : correct = False;
6407 : } else {
6408 5 : printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6409 : }
6410 :
6411 : /*--*/
6412 5 : status = cli_close(cli1, fnum1);
6413 5 : if (!NT_STATUS_IS_OK(status)) {
6414 0 : printf("close - 5 failed (%s)\n", nt_errstr(status));
6415 0 : return False;
6416 : }
6417 :
6418 : /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6419 5 : status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6420 5 : if (!NT_STATUS_IS_OK(status)) {
6421 0 : printf("getatr on file %s failed - %s ! \n",
6422 : fname1, nt_errstr(status));
6423 0 : correct = False;
6424 : } else {
6425 5 : if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6426 0 : printf("Renamed file %s has wrong attr 0x%x "
6427 : "(should be 0x%x)\n",
6428 : fname1,
6429 : attr,
6430 : (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6431 0 : correct = False;
6432 : } else {
6433 5 : printf("Renamed file %s has archive bit set\n", fname1);
6434 : }
6435 : }
6436 :
6437 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6438 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6439 :
6440 5 : if (!torture_close_connection(cli1)) {
6441 0 : correct = False;
6442 : }
6443 :
6444 5 : return correct;
6445 : }
6446 :
6447 : /*
6448 : Test rename into a directory with an ACL denying it.
6449 : */
6450 4 : static bool run_rename_access(int dummy)
6451 : {
6452 : static struct cli_state *cli = NULL;
6453 : static struct cli_state *posix_cli = NULL;
6454 4 : const char *src = "test.txt";
6455 4 : const char *dname = "dir";
6456 4 : const char *dst = "dir\\test.txt";
6457 4 : const char *dsrc = "test.dir";
6458 4 : const char *ddst = "dir\\test.dir";
6459 4 : uint16_t fnum = (uint16_t)-1;
6460 4 : struct security_descriptor *sd = NULL;
6461 4 : struct security_descriptor *newsd = NULL;
6462 : NTSTATUS status;
6463 4 : TALLOC_CTX *frame = NULL;
6464 :
6465 4 : frame = talloc_stackframe();
6466 4 : printf("starting rename access test\n");
6467 :
6468 : /* Windows connection. */
6469 4 : if (!torture_open_connection(&cli, 0)) {
6470 0 : goto fail;
6471 : }
6472 :
6473 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6474 :
6475 : /* Posix connection. */
6476 4 : if (!torture_open_connection(&posix_cli, 0)) {
6477 0 : goto fail;
6478 : }
6479 :
6480 4 : smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6481 :
6482 4 : status = torture_setup_unix_extensions(posix_cli);
6483 4 : if (!NT_STATUS_IS_OK(status)) {
6484 0 : goto fail;
6485 : }
6486 :
6487 : /* Start with a clean slate. */
6488 4 : cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6489 4 : cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6490 4 : cli_rmdir(cli, dsrc);
6491 4 : cli_rmdir(cli, ddst);
6492 4 : cli_rmdir(cli, dname);
6493 :
6494 : /*
6495 : * Setup the destination directory with a DENY ACE to
6496 : * prevent new files within it.
6497 : */
6498 4 : status = cli_ntcreate(cli,
6499 : dname,
6500 : 0,
6501 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6502 : WRITE_DAC_ACCESS|FILE_READ_DATA|
6503 : WRITE_OWNER_ACCESS,
6504 : FILE_ATTRIBUTE_DIRECTORY,
6505 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6506 : FILE_CREATE,
6507 : FILE_DIRECTORY_FILE,
6508 : 0,
6509 : &fnum,
6510 : NULL);
6511 4 : if (!NT_STATUS_IS_OK(status)) {
6512 0 : printf("Create of %s - %s\n", dname, nt_errstr(status));
6513 0 : goto fail;
6514 : }
6515 :
6516 4 : status = cli_query_secdesc(cli,
6517 : fnum,
6518 : frame,
6519 : &sd);
6520 4 : if (!NT_STATUS_IS_OK(status)) {
6521 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6522 : dname, nt_errstr(status));
6523 0 : goto fail;
6524 : }
6525 :
6526 4 : newsd = security_descriptor_dacl_create(frame,
6527 : 0,
6528 : NULL,
6529 : NULL,
6530 : SID_WORLD,
6531 : SEC_ACE_TYPE_ACCESS_DENIED,
6532 : SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6533 : 0,
6534 : NULL);
6535 4 : if (newsd == NULL) {
6536 0 : goto fail;
6537 : }
6538 4 : sd->dacl = security_acl_concatenate(frame,
6539 4 : newsd->dacl,
6540 4 : sd->dacl);
6541 4 : if (sd->dacl == NULL) {
6542 0 : goto fail;
6543 : }
6544 4 : status = cli_set_secdesc(cli, fnum, sd);
6545 4 : if (!NT_STATUS_IS_OK(status)) {
6546 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6547 : dname, nt_errstr(status));
6548 0 : goto fail;
6549 : }
6550 4 : status = cli_close(cli, fnum);
6551 4 : if (!NT_STATUS_IS_OK(status)) {
6552 0 : printf("close failed for %s (%s)\n",
6553 : dname, nt_errstr(status));
6554 0 : goto fail;
6555 : }
6556 : /* Now go around the back and chmod to 777 via POSIX. */
6557 4 : status = cli_posix_chmod(posix_cli, dname, 0777);
6558 4 : if (!NT_STATUS_IS_OK(status)) {
6559 0 : printf("cli_posix_chmod failed for %s (%s)\n",
6560 : dname, nt_errstr(status));
6561 0 : goto fail;
6562 : }
6563 :
6564 : /* Check we can't create a file within dname via Windows. */
6565 4 : status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6566 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6567 0 : cli_close(posix_cli, fnum);
6568 0 : printf("Create of %s should be ACCESS denied, was %s\n",
6569 : dst, nt_errstr(status));
6570 0 : goto fail;
6571 : }
6572 :
6573 : /* Make the sample file/directory. */
6574 4 : status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6575 4 : if (!NT_STATUS_IS_OK(status)) {
6576 0 : printf("open of %s failed (%s)\n", src, nt_errstr(status));
6577 0 : goto fail;
6578 : }
6579 4 : status = cli_close(cli, fnum);
6580 4 : if (!NT_STATUS_IS_OK(status)) {
6581 0 : printf("cli_close failed (%s)\n", nt_errstr(status));
6582 0 : goto fail;
6583 : }
6584 :
6585 4 : status = cli_mkdir(cli, dsrc);
6586 4 : if (!NT_STATUS_IS_OK(status)) {
6587 0 : printf("cli_mkdir of %s failed (%s)\n",
6588 : dsrc, nt_errstr(status));
6589 0 : goto fail;
6590 : }
6591 :
6592 : /*
6593 : * OK - renames of the new file and directory into the
6594 : * dst directory should fail.
6595 : */
6596 :
6597 4 : status = cli_rename(cli, src, dst, false);
6598 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6599 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6600 : src, dst, nt_errstr(status));
6601 0 : goto fail;
6602 : }
6603 4 : status = cli_rename(cli, dsrc, ddst, false);
6604 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6605 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6606 : src, dst, nt_errstr(status));
6607 0 : goto fail;
6608 : }
6609 :
6610 4 : TALLOC_FREE(frame);
6611 4 : return true;
6612 :
6613 0 : fail:
6614 :
6615 0 : if (posix_cli) {
6616 0 : torture_close_connection(posix_cli);
6617 : }
6618 :
6619 0 : if (cli) {
6620 0 : if (fnum != (uint16_t)-1) {
6621 0 : cli_close(cli, fnum);
6622 : }
6623 0 : cli_unlink(cli, src,
6624 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6625 0 : cli_unlink(cli, dst,
6626 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6627 0 : cli_rmdir(cli, dsrc);
6628 0 : cli_rmdir(cli, ddst);
6629 0 : cli_rmdir(cli, dname);
6630 :
6631 0 : torture_close_connection(cli);
6632 : }
6633 :
6634 0 : TALLOC_FREE(frame);
6635 0 : return false;
6636 : }
6637 :
6638 : /*
6639 : Test owner rights ACE.
6640 : */
6641 4 : static bool run_owner_rights(int dummy)
6642 : {
6643 : static struct cli_state *cli = NULL;
6644 4 : const char *fname = "owner_rights.txt";
6645 4 : uint16_t fnum = (uint16_t)-1;
6646 4 : struct security_descriptor *sd = NULL;
6647 4 : struct security_descriptor *newsd = NULL;
6648 : NTSTATUS status;
6649 4 : TALLOC_CTX *frame = NULL;
6650 :
6651 4 : frame = talloc_stackframe();
6652 4 : printf("starting owner rights test\n");
6653 :
6654 : /* Windows connection. */
6655 4 : if (!torture_open_connection(&cli, 0)) {
6656 0 : goto fail;
6657 : }
6658 :
6659 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6660 :
6661 : /* Start with a clean slate. */
6662 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6663 :
6664 : /* Create the test file. */
6665 : /* Now try and open for read and write-dac. */
6666 4 : status = cli_ntcreate(cli,
6667 : fname,
6668 : 0,
6669 : GENERIC_ALL_ACCESS,
6670 : FILE_ATTRIBUTE_NORMAL,
6671 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6672 : FILE_SHARE_DELETE,
6673 : FILE_CREATE,
6674 : 0,
6675 : 0,
6676 : &fnum,
6677 : NULL);
6678 4 : if (!NT_STATUS_IS_OK(status)) {
6679 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6680 0 : goto fail;
6681 : }
6682 :
6683 : /* Get the original SD. */
6684 4 : status = cli_query_secdesc(cli,
6685 : fnum,
6686 : frame,
6687 : &sd);
6688 4 : if (!NT_STATUS_IS_OK(status)) {
6689 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6690 : fname, nt_errstr(status));
6691 0 : goto fail;
6692 : }
6693 :
6694 : /*
6695 : * Add an "owner-rights" ACE denying WRITE_DATA,
6696 : * and an "owner-rights" ACE allowing READ_DATA.
6697 : */
6698 :
6699 4 : newsd = security_descriptor_dacl_create(frame,
6700 : 0,
6701 : NULL,
6702 : NULL,
6703 : SID_OWNER_RIGHTS,
6704 : SEC_ACE_TYPE_ACCESS_DENIED,
6705 : FILE_WRITE_DATA,
6706 : 0,
6707 : SID_OWNER_RIGHTS,
6708 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6709 : FILE_READ_DATA,
6710 : 0,
6711 : NULL);
6712 4 : if (newsd == NULL) {
6713 0 : goto fail;
6714 : }
6715 4 : sd->dacl = security_acl_concatenate(frame,
6716 4 : newsd->dacl,
6717 4 : sd->dacl);
6718 4 : if (sd->dacl == NULL) {
6719 0 : goto fail;
6720 : }
6721 4 : status = cli_set_secdesc(cli, fnum, sd);
6722 4 : if (!NT_STATUS_IS_OK(status)) {
6723 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6724 : fname, nt_errstr(status));
6725 0 : goto fail;
6726 : }
6727 4 : status = cli_close(cli, fnum);
6728 4 : if (!NT_STATUS_IS_OK(status)) {
6729 0 : printf("close failed for %s (%s)\n",
6730 : fname, nt_errstr(status));
6731 0 : goto fail;
6732 : }
6733 4 : fnum = (uint16_t)-1;
6734 :
6735 : /* Try and open for FILE_WRITE_DATA */
6736 4 : status = cli_ntcreate(cli,
6737 : fname,
6738 : 0,
6739 : FILE_WRITE_DATA,
6740 : FILE_ATTRIBUTE_NORMAL,
6741 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6742 : FILE_SHARE_DELETE,
6743 : FILE_OPEN,
6744 : 0,
6745 : 0,
6746 : &fnum,
6747 : NULL);
6748 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6749 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6750 0 : goto fail;
6751 : }
6752 :
6753 : /* Now try and open for FILE_READ_DATA */
6754 4 : status = cli_ntcreate(cli,
6755 : fname,
6756 : 0,
6757 : FILE_READ_DATA,
6758 : FILE_ATTRIBUTE_NORMAL,
6759 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6760 : FILE_SHARE_DELETE,
6761 : FILE_OPEN,
6762 : 0,
6763 : 0,
6764 : &fnum,
6765 : NULL);
6766 4 : if (!NT_STATUS_IS_OK(status)) {
6767 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6768 0 : goto fail;
6769 : }
6770 :
6771 4 : status = cli_close(cli, fnum);
6772 4 : if (!NT_STATUS_IS_OK(status)) {
6773 0 : printf("close failed for %s (%s)\n",
6774 : fname, nt_errstr(status));
6775 0 : goto fail;
6776 : }
6777 :
6778 : /* Restore clean slate. */
6779 4 : TALLOC_FREE(sd);
6780 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6781 :
6782 : /* Create the test file. */
6783 4 : status = cli_ntcreate(cli,
6784 : fname,
6785 : 0,
6786 : GENERIC_ALL_ACCESS,
6787 : FILE_ATTRIBUTE_NORMAL,
6788 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6789 : FILE_SHARE_DELETE,
6790 : FILE_CREATE,
6791 : 0,
6792 : 0,
6793 : &fnum,
6794 : NULL);
6795 4 : if (!NT_STATUS_IS_OK(status)) {
6796 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6797 0 : goto fail;
6798 : }
6799 :
6800 : /* Get the original SD. */
6801 4 : status = cli_query_secdesc(cli,
6802 : fnum,
6803 : frame,
6804 : &sd);
6805 4 : if (!NT_STATUS_IS_OK(status)) {
6806 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6807 : fname, nt_errstr(status));
6808 0 : goto fail;
6809 : }
6810 :
6811 : /*
6812 : * Add an "owner-rights ACE denying WRITE_DATA,
6813 : * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6814 : */
6815 :
6816 4 : newsd = security_descriptor_dacl_create(frame,
6817 : 0,
6818 : NULL,
6819 : NULL,
6820 : SID_OWNER_RIGHTS,
6821 : SEC_ACE_TYPE_ACCESS_DENIED,
6822 : FILE_WRITE_DATA,
6823 : 0,
6824 : SID_OWNER_RIGHTS,
6825 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6826 : FILE_READ_DATA|FILE_WRITE_DATA,
6827 : 0,
6828 : NULL);
6829 4 : if (newsd == NULL) {
6830 0 : goto fail;
6831 : }
6832 4 : sd->dacl = security_acl_concatenate(frame,
6833 4 : newsd->dacl,
6834 4 : sd->dacl);
6835 4 : if (sd->dacl == NULL) {
6836 0 : goto fail;
6837 : }
6838 4 : status = cli_set_secdesc(cli, fnum, sd);
6839 4 : if (!NT_STATUS_IS_OK(status)) {
6840 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6841 : fname, nt_errstr(status));
6842 0 : goto fail;
6843 : }
6844 4 : status = cli_close(cli, fnum);
6845 4 : if (!NT_STATUS_IS_OK(status)) {
6846 0 : printf("close failed for %s (%s)\n",
6847 : fname, nt_errstr(status));
6848 0 : goto fail;
6849 : }
6850 4 : fnum = (uint16_t)-1;
6851 :
6852 : /* Try and open for FILE_WRITE_DATA */
6853 4 : status = cli_ntcreate(cli,
6854 : fname,
6855 : 0,
6856 : FILE_WRITE_DATA,
6857 : FILE_ATTRIBUTE_NORMAL,
6858 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6859 : FILE_SHARE_DELETE,
6860 : FILE_OPEN,
6861 : 0,
6862 : 0,
6863 : &fnum,
6864 : NULL);
6865 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6866 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6867 0 : goto fail;
6868 : }
6869 :
6870 : /* Now try and open for FILE_READ_DATA */
6871 4 : status = cli_ntcreate(cli,
6872 : fname,
6873 : 0,
6874 : FILE_READ_DATA,
6875 : FILE_ATTRIBUTE_NORMAL,
6876 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6877 : FILE_SHARE_DELETE,
6878 : FILE_OPEN,
6879 : 0,
6880 : 0,
6881 : &fnum,
6882 : NULL);
6883 4 : if (!NT_STATUS_IS_OK(status)) {
6884 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6885 0 : goto fail;
6886 : }
6887 :
6888 4 : status = cli_close(cli, fnum);
6889 4 : if (!NT_STATUS_IS_OK(status)) {
6890 0 : printf("close failed for %s (%s)\n",
6891 : fname, nt_errstr(status));
6892 0 : goto fail;
6893 : }
6894 :
6895 : /* Restore clean slate. */
6896 4 : TALLOC_FREE(sd);
6897 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6898 :
6899 :
6900 : /* Create the test file. */
6901 4 : status = cli_ntcreate(cli,
6902 : fname,
6903 : 0,
6904 : GENERIC_ALL_ACCESS,
6905 : FILE_ATTRIBUTE_NORMAL,
6906 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6907 : FILE_SHARE_DELETE,
6908 : FILE_CREATE,
6909 : 0,
6910 : 0,
6911 : &fnum,
6912 : NULL);
6913 4 : if (!NT_STATUS_IS_OK(status)) {
6914 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6915 0 : goto fail;
6916 : }
6917 :
6918 : /* Get the original SD. */
6919 4 : status = cli_query_secdesc(cli,
6920 : fnum,
6921 : frame,
6922 : &sd);
6923 4 : if (!NT_STATUS_IS_OK(status)) {
6924 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6925 : fname, nt_errstr(status));
6926 0 : goto fail;
6927 : }
6928 :
6929 : /*
6930 : * Add an "authenticated users" ACE allowing READ_DATA,
6931 : * add an "owner-rights" denying READ_DATA,
6932 : * and an "authenticated users" ACE allowing WRITE_DATA.
6933 : */
6934 :
6935 4 : newsd = security_descriptor_dacl_create(frame,
6936 : 0,
6937 : NULL,
6938 : NULL,
6939 : SID_NT_AUTHENTICATED_USERS,
6940 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6941 : FILE_READ_DATA,
6942 : 0,
6943 : SID_OWNER_RIGHTS,
6944 : SEC_ACE_TYPE_ACCESS_DENIED,
6945 : FILE_READ_DATA,
6946 : 0,
6947 : SID_NT_AUTHENTICATED_USERS,
6948 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6949 : FILE_WRITE_DATA,
6950 : 0,
6951 : NULL);
6952 4 : if (newsd == NULL) {
6953 0 : printf("newsd == NULL\n");
6954 0 : goto fail;
6955 : }
6956 4 : sd->dacl = security_acl_concatenate(frame,
6957 4 : newsd->dacl,
6958 4 : sd->dacl);
6959 4 : if (sd->dacl == NULL) {
6960 0 : printf("sd->dacl == NULL\n");
6961 0 : goto fail;
6962 : }
6963 4 : status = cli_set_secdesc(cli, fnum, sd);
6964 4 : if (!NT_STATUS_IS_OK(status)) {
6965 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6966 : fname, nt_errstr(status));
6967 0 : goto fail;
6968 : }
6969 4 : status = cli_close(cli, fnum);
6970 4 : if (!NT_STATUS_IS_OK(status)) {
6971 0 : printf("close failed for %s (%s)\n",
6972 : fname, nt_errstr(status));
6973 0 : goto fail;
6974 : }
6975 4 : fnum = (uint16_t)-1;
6976 :
6977 : /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
6978 4 : status = cli_ntcreate(cli,
6979 : fname,
6980 : 0,
6981 : FILE_READ_DATA|FILE_WRITE_DATA,
6982 : FILE_ATTRIBUTE_NORMAL,
6983 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6984 : FILE_SHARE_DELETE,
6985 : FILE_OPEN,
6986 : 0,
6987 : 0,
6988 : &fnum,
6989 : NULL);
6990 4 : if (!NT_STATUS_IS_OK(status)) {
6991 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6992 0 : goto fail;
6993 : }
6994 :
6995 4 : status = cli_close(cli, fnum);
6996 4 : if (!NT_STATUS_IS_OK(status)) {
6997 0 : printf("close failed for %s (%s)\n",
6998 : fname, nt_errstr(status));
6999 0 : goto fail;
7000 : }
7001 :
7002 4 : cli_unlink(cli, fname,
7003 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7004 :
7005 4 : TALLOC_FREE(frame);
7006 4 : return true;
7007 :
7008 0 : fail:
7009 :
7010 0 : if (cli) {
7011 0 : if (fnum != (uint16_t)-1) {
7012 0 : cli_close(cli, fnum);
7013 : }
7014 0 : cli_unlink(cli, fname,
7015 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7016 0 : torture_close_connection(cli);
7017 : }
7018 :
7019 0 : TALLOC_FREE(frame);
7020 0 : return false;
7021 : }
7022 :
7023 : /*
7024 : * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7025 : * Note this test only works with a user with SeSecurityPrivilege set.
7026 : *
7027 : * NB. This is also tested in samba3.base.createx_access
7028 : * but this makes it very explicit what we're looking for.
7029 : */
7030 2 : static bool run_smb1_system_security(int dummy)
7031 : {
7032 : static struct cli_state *cli = NULL;
7033 2 : const char *fname = "system_security.txt";
7034 2 : uint16_t fnum = (uint16_t)-1;
7035 : NTSTATUS status;
7036 2 : TALLOC_CTX *frame = NULL;
7037 :
7038 2 : frame = talloc_stackframe();
7039 2 : printf("starting smb1 system security test\n");
7040 :
7041 : /* SMB1 connection - torture_open_connection() forces this. */
7042 2 : if (!torture_open_connection(&cli, 0)) {
7043 0 : goto fail;
7044 : }
7045 :
7046 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
7047 :
7048 : /* Start with a clean slate. */
7049 2 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7050 :
7051 : /* Create the test file. */
7052 2 : status = cli_ntcreate(cli,
7053 : fname,
7054 : 0,
7055 : GENERIC_ALL_ACCESS,
7056 : FILE_ATTRIBUTE_NORMAL,
7057 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7058 : FILE_SHARE_DELETE,
7059 : FILE_CREATE,
7060 : 0,
7061 : 0,
7062 : &fnum,
7063 : NULL);
7064 2 : if (!NT_STATUS_IS_OK(status)) {
7065 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7066 0 : goto fail;
7067 : }
7068 :
7069 2 : status = cli_close(cli, fnum);
7070 :
7071 : /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7072 : /*
7073 : * On SMB1 this succeeds - SMB2 it fails,
7074 : * see the SMB2-SACL test.
7075 : */
7076 2 : status = cli_ntcreate(cli,
7077 : fname,
7078 : 0,
7079 : SEC_FLAG_SYSTEM_SECURITY,
7080 : FILE_ATTRIBUTE_NORMAL,
7081 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7082 : FILE_SHARE_DELETE,
7083 : FILE_OPEN,
7084 : 0,
7085 : 0,
7086 : &fnum,
7087 : NULL);
7088 2 : if (!NT_STATUS_IS_OK(status)) {
7089 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7090 0 : goto fail;
7091 : }
7092 :
7093 2 : status = cli_close(cli, fnum);
7094 :
7095 2 : cli_unlink(cli, fname,
7096 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7097 :
7098 2 : torture_close_connection(cli);
7099 2 : TALLOC_FREE(frame);
7100 2 : return true;
7101 :
7102 0 : fail:
7103 :
7104 0 : if (cli) {
7105 0 : if (fnum != (uint16_t)-1) {
7106 0 : cli_close(cli, fnum);
7107 : }
7108 0 : cli_unlink(cli, fname,
7109 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7110 0 : torture_close_connection(cli);
7111 : }
7112 :
7113 0 : TALLOC_FREE(frame);
7114 0 : return false;
7115 : }
7116 :
7117 0 : static bool run_pipe_number(int dummy)
7118 : {
7119 : struct cli_state *cli1;
7120 0 : const char *pipe_name = "\\SPOOLSS";
7121 : uint16_t fnum;
7122 0 : int num_pipes = 0;
7123 : NTSTATUS status;
7124 :
7125 0 : printf("starting pipenumber test\n");
7126 0 : if (!torture_open_connection(&cli1, 0)) {
7127 0 : return False;
7128 : }
7129 :
7130 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7131 : while(1) {
7132 0 : status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7133 : FILE_ATTRIBUTE_NORMAL,
7134 : FILE_SHARE_READ|FILE_SHARE_WRITE,
7135 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
7136 0 : if (!NT_STATUS_IS_OK(status)) {
7137 0 : printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7138 0 : break;
7139 : }
7140 0 : num_pipes++;
7141 0 : printf("\r%6d", num_pipes);
7142 : }
7143 :
7144 0 : printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7145 0 : torture_close_connection(cli1);
7146 0 : return True;
7147 : }
7148 :
7149 : /*
7150 : Test open mode returns on read-only files.
7151 : */
7152 5 : static bool run_opentest(int dummy)
7153 : {
7154 : static struct cli_state *cli1;
7155 : static struct cli_state *cli2;
7156 5 : const char *fname = "\\readonly.file";
7157 : uint16_t fnum1, fnum2;
7158 : char buf[20];
7159 : off_t fsize;
7160 5 : bool correct = True;
7161 : char *tmp_path;
7162 : NTSTATUS status;
7163 :
7164 5 : printf("starting open test\n");
7165 :
7166 5 : if (!torture_open_connection(&cli1, 0)) {
7167 0 : return False;
7168 : }
7169 :
7170 5 : cli_setatr(cli1, fname, 0, 0);
7171 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7172 :
7173 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7174 :
7175 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7176 5 : if (!NT_STATUS_IS_OK(status)) {
7177 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7178 0 : return False;
7179 : }
7180 :
7181 5 : status = cli_close(cli1, fnum1);
7182 5 : if (!NT_STATUS_IS_OK(status)) {
7183 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7184 0 : return False;
7185 : }
7186 :
7187 5 : status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7188 5 : if (!NT_STATUS_IS_OK(status)) {
7189 0 : printf("cli_setatr failed (%s)\n", nt_errstr(status));
7190 0 : return False;
7191 : }
7192 :
7193 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7194 5 : if (!NT_STATUS_IS_OK(status)) {
7195 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7196 0 : return False;
7197 : }
7198 :
7199 : /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7200 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7201 :
7202 5 : if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7203 5 : NT_STATUS_ACCESS_DENIED)) {
7204 4 : printf("correct error code ERRDOS/ERRnoaccess returned\n");
7205 : }
7206 :
7207 5 : printf("finished open test 1\n");
7208 :
7209 5 : cli_close(cli1, fnum1);
7210 :
7211 : /* Now try not readonly and ensure ERRbadshare is returned. */
7212 :
7213 5 : cli_setatr(cli1, fname, 0, 0);
7214 :
7215 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7216 5 : if (!NT_STATUS_IS_OK(status)) {
7217 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7218 0 : return False;
7219 : }
7220 :
7221 : /* This will fail - but the error should be ERRshare. */
7222 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7223 :
7224 5 : if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7225 5 : NT_STATUS_SHARING_VIOLATION)) {
7226 5 : printf("correct error code ERRDOS/ERRbadshare returned\n");
7227 : }
7228 :
7229 5 : status = cli_close(cli1, fnum1);
7230 5 : if (!NT_STATUS_IS_OK(status)) {
7231 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7232 0 : return False;
7233 : }
7234 :
7235 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7236 :
7237 5 : printf("finished open test 2\n");
7238 :
7239 : /* Test truncate open disposition on file opened for read. */
7240 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7241 5 : if (!NT_STATUS_IS_OK(status)) {
7242 0 : printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7243 0 : return False;
7244 : }
7245 :
7246 : /* write 20 bytes. */
7247 :
7248 5 : memset(buf, '\0', 20);
7249 :
7250 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7251 5 : if (!NT_STATUS_IS_OK(status)) {
7252 0 : printf("write failed (%s)\n", nt_errstr(status));
7253 0 : correct = False;
7254 : }
7255 :
7256 5 : status = cli_close(cli1, fnum1);
7257 5 : if (!NT_STATUS_IS_OK(status)) {
7258 0 : printf("(3) close1 failed (%s)\n", nt_errstr(status));
7259 0 : return False;
7260 : }
7261 :
7262 : /* Ensure size == 20. */
7263 5 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7264 5 : if (!NT_STATUS_IS_OK(status)) {
7265 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7266 0 : return False;
7267 : }
7268 :
7269 5 : if (fsize != 20) {
7270 0 : printf("(3) file size != 20\n");
7271 0 : return False;
7272 : }
7273 :
7274 : /* Now test if we can truncate a file opened for readonly. */
7275 5 : status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7276 5 : if (!NT_STATUS_IS_OK(status)) {
7277 0 : printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7278 0 : return False;
7279 : }
7280 :
7281 5 : status = cli_close(cli1, fnum1);
7282 5 : if (!NT_STATUS_IS_OK(status)) {
7283 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7284 0 : return False;
7285 : }
7286 :
7287 : /* Ensure size == 0. */
7288 5 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7289 5 : if (!NT_STATUS_IS_OK(status)) {
7290 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7291 0 : return False;
7292 : }
7293 :
7294 5 : if (fsize != 0) {
7295 0 : printf("(3) file size != 0\n");
7296 0 : return False;
7297 : }
7298 5 : printf("finished open test 3\n");
7299 :
7300 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7301 :
7302 5 : printf("Do ctemp tests\n");
7303 5 : status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7304 5 : if (!NT_STATUS_IS_OK(status)) {
7305 0 : printf("ctemp failed (%s)\n", nt_errstr(status));
7306 0 : return False;
7307 : }
7308 :
7309 5 : printf("ctemp gave path %s\n", tmp_path);
7310 5 : status = cli_close(cli1, fnum1);
7311 5 : if (!NT_STATUS_IS_OK(status)) {
7312 0 : printf("close of temp failed (%s)\n", nt_errstr(status));
7313 : }
7314 :
7315 5 : status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7316 5 : if (!NT_STATUS_IS_OK(status)) {
7317 0 : printf("unlink of temp failed (%s)\n", nt_errstr(status));
7318 : }
7319 :
7320 : /* Test the non-io opens... */
7321 :
7322 5 : if (!torture_open_connection(&cli2, 1)) {
7323 0 : return False;
7324 : }
7325 :
7326 5 : cli_setatr(cli2, fname, 0, 0);
7327 5 : cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7328 :
7329 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
7330 :
7331 5 : printf("TEST #1 testing 2 non-io opens (no delete)\n");
7332 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7333 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7334 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7335 5 : if (!NT_STATUS_IS_OK(status)) {
7336 0 : printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7337 0 : return False;
7338 : }
7339 :
7340 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7341 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7342 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7343 5 : if (!NT_STATUS_IS_OK(status)) {
7344 0 : printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7345 0 : return False;
7346 : }
7347 :
7348 5 : status = cli_close(cli1, fnum1);
7349 5 : if (!NT_STATUS_IS_OK(status)) {
7350 0 : printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7351 0 : return False;
7352 : }
7353 :
7354 5 : status = cli_close(cli2, fnum2);
7355 5 : if (!NT_STATUS_IS_OK(status)) {
7356 0 : printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7357 0 : return False;
7358 : }
7359 :
7360 5 : printf("non-io open test #1 passed.\n");
7361 :
7362 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7363 :
7364 5 : printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7365 :
7366 5 : status = cli_ntcreate(cli1, fname, 0,
7367 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7368 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7369 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7370 5 : if (!NT_STATUS_IS_OK(status)) {
7371 0 : printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7372 0 : return False;
7373 : }
7374 :
7375 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7376 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7377 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7378 5 : if (!NT_STATUS_IS_OK(status)) {
7379 0 : printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7380 0 : return False;
7381 : }
7382 :
7383 5 : status = cli_close(cli1, fnum1);
7384 5 : if (!NT_STATUS_IS_OK(status)) {
7385 0 : printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7386 0 : return False;
7387 : }
7388 :
7389 5 : status = cli_close(cli2, fnum2);
7390 5 : if (!NT_STATUS_IS_OK(status)) {
7391 0 : printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7392 0 : return False;
7393 : }
7394 :
7395 5 : printf("non-io open test #2 passed.\n");
7396 :
7397 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7398 :
7399 5 : printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7400 :
7401 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7402 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7403 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7404 5 : if (!NT_STATUS_IS_OK(status)) {
7405 0 : printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7406 0 : return False;
7407 : }
7408 :
7409 5 : status = cli_ntcreate(cli2, fname, 0,
7410 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7411 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7412 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7413 5 : if (!NT_STATUS_IS_OK(status)) {
7414 0 : printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7415 0 : return False;
7416 : }
7417 :
7418 5 : status = cli_close(cli1, fnum1);
7419 5 : if (!NT_STATUS_IS_OK(status)) {
7420 0 : printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7421 0 : return False;
7422 : }
7423 :
7424 5 : status = cli_close(cli2, fnum2);
7425 5 : if (!NT_STATUS_IS_OK(status)) {
7426 0 : printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7427 0 : return False;
7428 : }
7429 :
7430 5 : printf("non-io open test #3 passed.\n");
7431 :
7432 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7433 :
7434 5 : printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7435 :
7436 5 : status = cli_ntcreate(cli1, fname, 0,
7437 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7438 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7439 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7440 5 : if (!NT_STATUS_IS_OK(status)) {
7441 0 : printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7442 0 : return False;
7443 : }
7444 :
7445 5 : status = cli_ntcreate(cli2, fname, 0,
7446 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7447 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7448 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7449 5 : if (NT_STATUS_IS_OK(status)) {
7450 0 : printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7451 0 : return False;
7452 : }
7453 :
7454 5 : printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7455 :
7456 5 : status = cli_close(cli1, fnum1);
7457 5 : if (!NT_STATUS_IS_OK(status)) {
7458 0 : printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7459 0 : return False;
7460 : }
7461 :
7462 5 : printf("non-io open test #4 passed.\n");
7463 :
7464 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7465 :
7466 5 : printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7467 :
7468 5 : status = cli_ntcreate(cli1, fname, 0,
7469 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7470 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7471 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7472 5 : if (!NT_STATUS_IS_OK(status)) {
7473 0 : printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7474 0 : return False;
7475 : }
7476 :
7477 5 : status = cli_ntcreate(cli2, fname, 0,
7478 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7479 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7480 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7481 5 : if (!NT_STATUS_IS_OK(status)) {
7482 0 : printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7483 0 : return False;
7484 : }
7485 :
7486 5 : status = cli_close(cli1, fnum1);
7487 5 : if (!NT_STATUS_IS_OK(status)) {
7488 0 : printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7489 0 : return False;
7490 : }
7491 :
7492 5 : status = cli_close(cli2, fnum2);
7493 5 : if (!NT_STATUS_IS_OK(status)) {
7494 0 : printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7495 0 : return False;
7496 : }
7497 :
7498 5 : printf("non-io open test #5 passed.\n");
7499 :
7500 5 : printf("TEST #6 testing 1 non-io open, one io open\n");
7501 :
7502 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7503 :
7504 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7505 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7506 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7507 5 : if (!NT_STATUS_IS_OK(status)) {
7508 0 : printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7509 0 : return False;
7510 : }
7511 :
7512 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7513 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7514 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7515 5 : if (!NT_STATUS_IS_OK(status)) {
7516 0 : printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7517 0 : return False;
7518 : }
7519 :
7520 5 : status = cli_close(cli1, fnum1);
7521 5 : if (!NT_STATUS_IS_OK(status)) {
7522 0 : printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7523 0 : return False;
7524 : }
7525 :
7526 5 : status = cli_close(cli2, fnum2);
7527 5 : if (!NT_STATUS_IS_OK(status)) {
7528 0 : printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7529 0 : return False;
7530 : }
7531 :
7532 5 : printf("non-io open test #6 passed.\n");
7533 :
7534 5 : printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7535 :
7536 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7537 :
7538 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7539 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7540 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7541 5 : if (!NT_STATUS_IS_OK(status)) {
7542 0 : printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7543 0 : return False;
7544 : }
7545 :
7546 5 : status = cli_ntcreate(cli2, fname, 0,
7547 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7548 : FILE_ATTRIBUTE_NORMAL,
7549 : FILE_SHARE_READ|FILE_SHARE_DELETE,
7550 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7551 5 : if (NT_STATUS_IS_OK(status)) {
7552 0 : printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7553 0 : return False;
7554 : }
7555 :
7556 5 : printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7557 :
7558 5 : status = cli_close(cli1, fnum1);
7559 5 : if (!NT_STATUS_IS_OK(status)) {
7560 0 : printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7561 0 : return False;
7562 : }
7563 :
7564 5 : printf("non-io open test #7 passed.\n");
7565 :
7566 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7567 :
7568 5 : printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7569 5 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7570 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7571 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7572 5 : if (!NT_STATUS_IS_OK(status)) {
7573 0 : printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7574 0 : correct = false;
7575 0 : goto out;
7576 : }
7577 :
7578 : /* Write to ensure we have to update the file time. */
7579 5 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7580 : NULL);
7581 5 : if (!NT_STATUS_IS_OK(status)) {
7582 0 : printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7583 0 : correct = false;
7584 0 : goto out;
7585 : }
7586 :
7587 5 : status = cli_close(cli1, fnum1);
7588 5 : if (!NT_STATUS_IS_OK(status)) {
7589 0 : printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7590 0 : correct = false;
7591 : }
7592 :
7593 10 : out:
7594 :
7595 5 : if (!torture_close_connection(cli1)) {
7596 0 : correct = False;
7597 : }
7598 5 : if (!torture_close_connection(cli2)) {
7599 0 : correct = False;
7600 : }
7601 :
7602 5 : return correct;
7603 : }
7604 :
7605 98 : NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7606 : {
7607 : uint16_t major, minor;
7608 : uint32_t caplow, caphigh;
7609 : NTSTATUS status;
7610 :
7611 98 : if (!SERVER_HAS_UNIX_CIFS(cli)) {
7612 0 : printf("Server doesn't support UNIX CIFS extensions.\n");
7613 0 : return NT_STATUS_NOT_SUPPORTED;
7614 : }
7615 :
7616 98 : status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7617 : &caphigh);
7618 98 : if (!NT_STATUS_IS_OK(status)) {
7619 0 : printf("Server didn't return UNIX CIFS extensions: %s\n",
7620 : nt_errstr(status));
7621 0 : return status;
7622 : }
7623 :
7624 98 : status = cli_set_unix_extensions_capabilities(cli, major, minor,
7625 : caplow, caphigh);
7626 98 : if (!NT_STATUS_IS_OK(status)) {
7627 0 : printf("Server doesn't support setting UNIX CIFS extensions: "
7628 : "%s.\n", nt_errstr(status));
7629 0 : return status;
7630 : }
7631 :
7632 98 : return NT_STATUS_OK;
7633 : }
7634 :
7635 : /*
7636 : Test POSIX open /mkdir calls.
7637 : */
7638 4 : static bool run_simple_posix_open_test(int dummy)
7639 : {
7640 : static struct cli_state *cli1;
7641 4 : const char *fname = "posix:file";
7642 4 : const char *hname = "posix:hlink";
7643 4 : const char *sname = "posix:symlink";
7644 4 : const char *dname = "posix:dir";
7645 : char buf[10];
7646 4 : char *target = NULL;
7647 4 : uint16_t fnum1 = (uint16_t)-1;
7648 : SMB_STRUCT_STAT sbuf;
7649 4 : bool correct = false;
7650 : NTSTATUS status;
7651 : size_t nread;
7652 4 : const char *fname_windows = "windows_file";
7653 4 : uint16_t fnum2 = (uint16_t)-1;
7654 :
7655 4 : printf("Starting simple POSIX open test\n");
7656 :
7657 4 : if (!torture_open_connection(&cli1, 0)) {
7658 0 : return false;
7659 : }
7660 :
7661 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7662 :
7663 4 : status = torture_setup_unix_extensions(cli1);
7664 4 : if (!NT_STATUS_IS_OK(status)) {
7665 0 : return false;
7666 : }
7667 :
7668 4 : cli_setatr(cli1, fname, 0, 0);
7669 4 : cli_posix_unlink(cli1, fname);
7670 4 : cli_setatr(cli1, dname, 0, 0);
7671 4 : cli_posix_rmdir(cli1, dname);
7672 4 : cli_setatr(cli1, hname, 0, 0);
7673 4 : cli_posix_unlink(cli1, hname);
7674 4 : cli_setatr(cli1, sname, 0, 0);
7675 4 : cli_posix_unlink(cli1, sname);
7676 4 : cli_setatr(cli1, fname_windows, 0, 0);
7677 4 : cli_posix_unlink(cli1, fname_windows);
7678 :
7679 : /* Create a directory. */
7680 4 : status = cli_posix_mkdir(cli1, dname, 0777);
7681 4 : if (!NT_STATUS_IS_OK(status)) {
7682 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7683 0 : goto out;
7684 : }
7685 :
7686 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7687 : 0600, &fnum1);
7688 4 : if (!NT_STATUS_IS_OK(status)) {
7689 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7690 0 : goto out;
7691 : }
7692 :
7693 : /* Test ftruncate - set file size. */
7694 4 : status = cli_ftruncate(cli1, fnum1, 1000);
7695 4 : if (!NT_STATUS_IS_OK(status)) {
7696 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7697 0 : goto out;
7698 : }
7699 :
7700 : /* Ensure st_size == 1000 */
7701 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7702 4 : if (!NT_STATUS_IS_OK(status)) {
7703 0 : printf("stat failed (%s)\n", nt_errstr(status));
7704 0 : goto out;
7705 : }
7706 :
7707 4 : if (sbuf.st_ex_size != 1000) {
7708 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7709 0 : goto out;
7710 : }
7711 :
7712 : /* Ensure st_mode == 0600 */
7713 4 : if ((sbuf.st_ex_mode & 07777) != 0600) {
7714 0 : printf("posix_open - bad permissions 0%o != 0600\n",
7715 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
7716 0 : goto out;
7717 : }
7718 :
7719 : /* Test ftruncate - set file size back to zero. */
7720 4 : status = cli_ftruncate(cli1, fnum1, 0);
7721 4 : if (!NT_STATUS_IS_OK(status)) {
7722 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7723 0 : goto out;
7724 : }
7725 :
7726 4 : status = cli_close(cli1, fnum1);
7727 4 : if (!NT_STATUS_IS_OK(status)) {
7728 0 : printf("close failed (%s)\n", nt_errstr(status));
7729 0 : goto out;
7730 : }
7731 :
7732 : /* Now open the file again for read only. */
7733 4 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7734 4 : if (!NT_STATUS_IS_OK(status)) {
7735 0 : printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7736 0 : goto out;
7737 : }
7738 :
7739 : /* Now unlink while open. */
7740 4 : status = cli_posix_unlink(cli1, fname);
7741 4 : if (!NT_STATUS_IS_OK(status)) {
7742 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7743 0 : goto out;
7744 : }
7745 :
7746 4 : status = cli_close(cli1, fnum1);
7747 4 : if (!NT_STATUS_IS_OK(status)) {
7748 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7749 0 : goto out;
7750 : }
7751 :
7752 : /* Ensure the file has gone. */
7753 4 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7754 4 : if (NT_STATUS_IS_OK(status)) {
7755 0 : printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7756 0 : goto out;
7757 : }
7758 :
7759 : /* Create again to test open with O_TRUNC. */
7760 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7761 4 : if (!NT_STATUS_IS_OK(status)) {
7762 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7763 0 : goto out;
7764 : }
7765 :
7766 : /* Test ftruncate - set file size. */
7767 4 : status = cli_ftruncate(cli1, fnum1, 1000);
7768 4 : if (!NT_STATUS_IS_OK(status)) {
7769 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7770 0 : goto out;
7771 : }
7772 :
7773 : /* Ensure st_size == 1000 */
7774 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7775 4 : if (!NT_STATUS_IS_OK(status)) {
7776 0 : printf("stat failed (%s)\n", nt_errstr(status));
7777 0 : goto out;
7778 : }
7779 :
7780 4 : if (sbuf.st_ex_size != 1000) {
7781 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7782 0 : goto out;
7783 : }
7784 :
7785 4 : status = cli_close(cli1, fnum1);
7786 4 : if (!NT_STATUS_IS_OK(status)) {
7787 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7788 0 : goto out;
7789 : }
7790 :
7791 : /* Re-open with O_TRUNC. */
7792 4 : status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7793 4 : if (!NT_STATUS_IS_OK(status)) {
7794 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7795 0 : goto out;
7796 : }
7797 :
7798 : /* Ensure st_size == 0 */
7799 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7800 4 : if (!NT_STATUS_IS_OK(status)) {
7801 0 : printf("stat failed (%s)\n", nt_errstr(status));
7802 0 : goto out;
7803 : }
7804 :
7805 4 : if (sbuf.st_ex_size != 0) {
7806 0 : printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7807 0 : goto out;
7808 : }
7809 :
7810 4 : status = cli_close(cli1, fnum1);
7811 4 : if (!NT_STATUS_IS_OK(status)) {
7812 0 : printf("close failed (%s)\n", nt_errstr(status));
7813 0 : goto out;
7814 : }
7815 :
7816 4 : status = cli_posix_unlink(cli1, fname);
7817 4 : if (!NT_STATUS_IS_OK(status)) {
7818 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7819 0 : goto out;
7820 : }
7821 :
7822 4 : status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7823 4 : if (!NT_STATUS_IS_OK(status)) {
7824 0 : printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7825 : dname, nt_errstr(status));
7826 0 : goto out;
7827 : }
7828 :
7829 4 : cli_close(cli1, fnum1);
7830 :
7831 : /* What happens when we try and POSIX open a directory for write ? */
7832 4 : status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7833 4 : if (NT_STATUS_IS_OK(status)) {
7834 0 : printf("POSIX open of directory %s succeeded, "
7835 : "should have failed.\n",
7836 : dname);
7837 0 : goto out;
7838 : } else {
7839 4 : if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7840 4 : NT_STATUS_FILE_IS_A_DIRECTORY)) {
7841 0 : goto out;
7842 : }
7843 : }
7844 :
7845 : /* Create the file. */
7846 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7847 : 0600, &fnum1);
7848 4 : if (!NT_STATUS_IS_OK(status)) {
7849 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7850 0 : goto out;
7851 : }
7852 :
7853 : /* Write some data into it. */
7854 4 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7855 : NULL);
7856 4 : if (!NT_STATUS_IS_OK(status)) {
7857 0 : printf("cli_write failed: %s\n", nt_errstr(status));
7858 0 : goto out;
7859 : }
7860 :
7861 4 : cli_close(cli1, fnum1);
7862 :
7863 : /* Now create a hardlink. */
7864 4 : status = cli_posix_hardlink(cli1, fname, hname);
7865 4 : if (!NT_STATUS_IS_OK(status)) {
7866 0 : printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7867 0 : goto out;
7868 : }
7869 :
7870 : /* Now create a symlink. */
7871 4 : status = cli_posix_symlink(cli1, fname, sname);
7872 4 : if (!NT_STATUS_IS_OK(status)) {
7873 0 : printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7874 0 : goto out;
7875 : }
7876 :
7877 : /* Open the hardlink for read. */
7878 4 : status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7879 4 : if (!NT_STATUS_IS_OK(status)) {
7880 0 : printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7881 0 : goto out;
7882 : }
7883 :
7884 4 : status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7885 4 : if (!NT_STATUS_IS_OK(status)) {
7886 0 : printf("POSIX read of %s failed (%s)\n", hname,
7887 : nt_errstr(status));
7888 0 : goto out;
7889 4 : } else if (nread != 10) {
7890 0 : printf("POSIX read of %s failed. Received %ld, expected %d\n",
7891 : hname, (unsigned long)nread, 10);
7892 0 : goto out;
7893 : }
7894 :
7895 4 : if (memcmp(buf, "TEST DATA\n", 10)) {
7896 0 : printf("invalid data read from hardlink\n");
7897 0 : goto out;
7898 : }
7899 :
7900 : /* Do a POSIX lock/unlock. */
7901 4 : status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
7902 4 : if (!NT_STATUS_IS_OK(status)) {
7903 0 : printf("POSIX lock failed %s\n", nt_errstr(status));
7904 0 : goto out;
7905 : }
7906 :
7907 : /* Punch a hole in the locked area. */
7908 4 : status = cli_posix_unlock(cli1, fnum1, 10, 80);
7909 4 : if (!NT_STATUS_IS_OK(status)) {
7910 0 : printf("POSIX unlock failed %s\n", nt_errstr(status));
7911 0 : goto out;
7912 : }
7913 :
7914 4 : cli_close(cli1, fnum1);
7915 :
7916 : /* Open the symlink for read - this should fail. A POSIX
7917 : client should not be doing opens on a symlink. */
7918 4 : status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
7919 4 : if (NT_STATUS_IS_OK(status)) {
7920 0 : printf("POSIX open of %s succeeded (should have failed)\n", sname);
7921 0 : goto out;
7922 : } else {
7923 4 : if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
7924 4 : NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7925 0 : printf("POSIX open of %s should have failed "
7926 : "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
7927 : "failed with %s instead.\n",
7928 : sname, nt_errstr(status));
7929 0 : goto out;
7930 : }
7931 : }
7932 :
7933 4 : status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
7934 4 : if (!NT_STATUS_IS_OK(status)) {
7935 0 : printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
7936 0 : goto out;
7937 : }
7938 :
7939 4 : if (strcmp(target, fname) != 0) {
7940 0 : printf("POSIX readlink on %s failed to match name %s (read %s)\n",
7941 : sname, fname, target);
7942 0 : goto out;
7943 : }
7944 :
7945 4 : status = cli_posix_rmdir(cli1, dname);
7946 4 : if (!NT_STATUS_IS_OK(status)) {
7947 0 : printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
7948 0 : goto out;
7949 : }
7950 :
7951 : /* Check directory opens with a specific permission. */
7952 4 : status = cli_posix_mkdir(cli1, dname, 0700);
7953 4 : if (!NT_STATUS_IS_OK(status)) {
7954 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7955 0 : goto out;
7956 : }
7957 :
7958 : /* Ensure st_mode == 0700 */
7959 4 : status = cli_posix_stat(cli1, dname, &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_mode & 07777) != 0700) {
7966 0 : printf("posix_mkdir - bad permissions 0%o != 0700\n",
7967 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
7968 0 : goto out;
7969 : }
7970 :
7971 : /*
7972 : * Now create a Windows file, and attempt a POSIX unlink.
7973 : * This should fail with a sharing violation but due to:
7974 : *
7975 : * [Bug 9571] Unlink after open causes smbd to panic
7976 : *
7977 : * ensure we've fixed the lock ordering violation.
7978 : */
7979 :
7980 4 : status = cli_ntcreate(cli1, fname_windows, 0,
7981 : FILE_READ_DATA|FILE_WRITE_DATA, 0,
7982 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7983 : FILE_CREATE,
7984 : 0x0, 0x0, &fnum2, NULL);
7985 4 : if (!NT_STATUS_IS_OK(status)) {
7986 0 : printf("Windows create of %s failed (%s)\n", fname_windows,
7987 : nt_errstr(status));
7988 0 : goto out;
7989 : }
7990 :
7991 : /* Now try posix_unlink. */
7992 4 : status = cli_posix_unlink(cli1, fname_windows);
7993 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7994 0 : printf("POSIX unlink of %s should fail "
7995 : "with NT_STATUS_SHARING_VIOLATION "
7996 : "got %s instead !\n",
7997 : fname_windows,
7998 : nt_errstr(status));
7999 0 : goto out;
8000 : }
8001 :
8002 4 : cli_close(cli1, fnum2);
8003 :
8004 4 : printf("Simple POSIX open test passed\n");
8005 4 : correct = true;
8006 :
8007 4 : out:
8008 :
8009 4 : if (fnum1 != (uint16_t)-1) {
8010 4 : cli_close(cli1, fnum1);
8011 4 : fnum1 = (uint16_t)-1;
8012 : }
8013 :
8014 4 : if (fnum2 != (uint16_t)-1) {
8015 4 : cli_close(cli1, fnum2);
8016 4 : fnum2 = (uint16_t)-1;
8017 : }
8018 :
8019 4 : cli_setatr(cli1, sname, 0, 0);
8020 4 : cli_posix_unlink(cli1, sname);
8021 4 : cli_setatr(cli1, hname, 0, 0);
8022 4 : cli_posix_unlink(cli1, hname);
8023 4 : cli_setatr(cli1, fname, 0, 0);
8024 4 : cli_posix_unlink(cli1, fname);
8025 4 : cli_setatr(cli1, dname, 0, 0);
8026 4 : cli_posix_rmdir(cli1, dname);
8027 4 : cli_setatr(cli1, fname_windows, 0, 0);
8028 4 : cli_posix_unlink(cli1, fname_windows);
8029 :
8030 4 : if (!torture_close_connection(cli1)) {
8031 0 : correct = false;
8032 : }
8033 :
8034 4 : return correct;
8035 : }
8036 :
8037 : /*
8038 : Test POSIX and Windows ACLs are rejected on symlinks.
8039 : */
8040 4 : static bool run_acl_symlink_test(int dummy)
8041 : {
8042 : static struct cli_state *cli;
8043 4 : const char *fname = "posix_file";
8044 4 : const char *sname = "posix_symlink";
8045 4 : uint16_t fnum = (uint16_t)-1;
8046 4 : bool correct = false;
8047 : NTSTATUS status;
8048 4 : char *posix_acl = NULL;
8049 4 : size_t posix_acl_len = 0;
8050 4 : char *posix_acl_sym = NULL;
8051 4 : size_t posix_acl_len_sym = 0;
8052 4 : struct security_descriptor *sd = NULL;
8053 4 : TALLOC_CTX *frame = NULL;
8054 :
8055 4 : frame = talloc_stackframe();
8056 :
8057 4 : printf("Starting acl symlink test\n");
8058 :
8059 4 : if (!torture_open_connection(&cli, 0)) {
8060 0 : TALLOC_FREE(frame);
8061 0 : return false;
8062 : }
8063 :
8064 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8065 :
8066 4 : status = torture_setup_unix_extensions(cli);
8067 4 : if (!NT_STATUS_IS_OK(status)) {
8068 0 : TALLOC_FREE(frame);
8069 0 : return false;
8070 : }
8071 :
8072 4 : cli_setatr(cli, fname, 0, 0);
8073 4 : cli_posix_unlink(cli, fname);
8074 4 : cli_setatr(cli, sname, 0, 0);
8075 4 : cli_posix_unlink(cli, sname);
8076 :
8077 4 : status = cli_ntcreate(cli,
8078 : fname,
8079 : 0,
8080 : READ_CONTROL_ACCESS,
8081 : 0,
8082 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8083 : FILE_CREATE,
8084 : 0x0,
8085 : 0x0,
8086 : &fnum,
8087 : NULL);
8088 :
8089 4 : if (!NT_STATUS_IS_OK(status)) {
8090 0 : printf("cli_ntcreate of %s failed (%s)\n",
8091 : fname,
8092 : nt_errstr(status));
8093 0 : goto out;
8094 : }
8095 :
8096 : /* Get the Windows ACL on the file. */
8097 4 : status = cli_query_secdesc(cli,
8098 : fnum,
8099 : frame,
8100 : &sd);
8101 4 : if (!NT_STATUS_IS_OK(status)) {
8102 0 : printf("cli_query_secdesc failed (%s)\n",
8103 : nt_errstr(status));
8104 0 : goto out;
8105 : }
8106 :
8107 : /* Get the POSIX ACL on the file. */
8108 4 : status = cli_posix_getacl(cli,
8109 : fname,
8110 : frame,
8111 : &posix_acl_len,
8112 : &posix_acl);
8113 :
8114 4 : if (!NT_STATUS_IS_OK(status)) {
8115 0 : printf("cli_posix_getacl failed (%s)\n",
8116 : nt_errstr(status));
8117 0 : goto out;
8118 : }
8119 :
8120 4 : status = cli_close(cli, fnum);
8121 4 : if (!NT_STATUS_IS_OK(status)) {
8122 0 : printf("close failed (%s)\n", nt_errstr(status));
8123 0 : goto out;
8124 : }
8125 4 : fnum = (uint16_t)-1;
8126 :
8127 : /* Now create a symlink. */
8128 4 : status = cli_posix_symlink(cli, fname, sname);
8129 4 : if (!NT_STATUS_IS_OK(status)) {
8130 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8131 : sname,
8132 : fname,
8133 : nt_errstr(status));
8134 0 : goto out;
8135 : }
8136 :
8137 : /* Open a handle on the symlink for SD set/get should fail. */
8138 4 : status = cli_ntcreate(cli,
8139 : sname,
8140 : 0,
8141 : READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8142 : 0,
8143 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8144 : FILE_OPEN,
8145 : 0x0,
8146 : 0x0,
8147 : &fnum,
8148 : NULL);
8149 :
8150 4 : if (NT_STATUS_IS_OK(status)) {
8151 0 : printf("Symlink open for getsd/setsd of %s "
8152 : "succeeded (should fail)\n",
8153 : sname);
8154 0 : goto out;
8155 : }
8156 :
8157 : /* Try a stat-open on the symlink, should also fail. */
8158 4 : status = cli_ntcreate(cli,
8159 : sname,
8160 : 0,
8161 : FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8162 : 0,
8163 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8164 : FILE_OPEN,
8165 : 0x0,
8166 : 0x0,
8167 : &fnum,
8168 : NULL);
8169 :
8170 4 : if (NT_STATUS_IS_OK(status)) {
8171 0 : printf("Stat-open of symlink succeeded (should fail)\n");
8172 0 : goto out;
8173 : }
8174 :
8175 : /* Get the POSIX ACL on the symlink pathname. Should fail. */
8176 4 : status = cli_posix_getacl(cli,
8177 : sname,
8178 : frame,
8179 : &posix_acl_len_sym,
8180 : &posix_acl_sym);
8181 :
8182 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8183 0 : printf("cli_posix_getacl on a symlink gave %s. "
8184 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8185 : nt_errstr(status));
8186 0 : goto out;
8187 : }
8188 :
8189 : /* Set the POSIX ACL on the symlink pathname. Should fail. */
8190 4 : status = cli_posix_setacl(cli,
8191 : sname,
8192 : posix_acl,
8193 : posix_acl_len);
8194 :
8195 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8196 0 : printf("cli_posix_setacl on a symlink gave %s. "
8197 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8198 : nt_errstr(status));
8199 0 : goto out;
8200 : }
8201 :
8202 4 : printf("ACL symlink test passed\n");
8203 4 : correct = true;
8204 :
8205 4 : out:
8206 :
8207 4 : if (fnum != (uint16_t)-1) {
8208 0 : cli_close(cli, fnum);
8209 0 : fnum = (uint16_t)-1;
8210 : }
8211 :
8212 4 : cli_setatr(cli, sname, 0, 0);
8213 4 : cli_posix_unlink(cli, sname);
8214 4 : cli_setatr(cli, fname, 0, 0);
8215 4 : cli_posix_unlink(cli, fname);
8216 :
8217 4 : if (!torture_close_connection(cli)) {
8218 0 : correct = false;
8219 : }
8220 :
8221 4 : TALLOC_FREE(frame);
8222 4 : return correct;
8223 : }
8224 :
8225 : /*
8226 : Test POSIX can delete a file containing streams.
8227 : */
8228 4 : static bool run_posix_stream_delete(int dummy)
8229 : {
8230 4 : struct cli_state *cli1 = NULL;
8231 4 : struct cli_state *cli2 = NULL;
8232 4 : const char *fname = "streamfile";
8233 4 : const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8234 4 : uint16_t fnum1 = (uint16_t)-1;
8235 4 : bool correct = false;
8236 : NTSTATUS status;
8237 4 : TALLOC_CTX *frame = NULL;
8238 :
8239 4 : frame = talloc_stackframe();
8240 :
8241 4 : printf("Starting POSIX stream delete test\n");
8242 :
8243 8 : if (!torture_open_connection(&cli1, 0) ||
8244 4 : !torture_open_connection(&cli2, 1)) {
8245 0 : TALLOC_FREE(frame);
8246 0 : return false;
8247 : }
8248 :
8249 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
8250 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
8251 :
8252 4 : status = torture_setup_unix_extensions(cli2);
8253 4 : if (!NT_STATUS_IS_OK(status)) {
8254 0 : goto out;
8255 : }
8256 :
8257 4 : cli_setatr(cli1, fname, 0, 0);
8258 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8259 :
8260 : /* Create the file. */
8261 4 : status = cli_ntcreate(cli1,
8262 : fname,
8263 : 0,
8264 : READ_CONTROL_ACCESS,
8265 : 0,
8266 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8267 : FILE_CREATE,
8268 : 0x0,
8269 : 0x0,
8270 : &fnum1,
8271 : NULL);
8272 :
8273 4 : if (!NT_STATUS_IS_OK(status)) {
8274 0 : printf("cli_ntcreate of %s failed (%s)\n",
8275 : fname,
8276 : nt_errstr(status));
8277 0 : goto out;
8278 : }
8279 :
8280 4 : status = cli_close(cli1, fnum1);
8281 4 : if (!NT_STATUS_IS_OK(status)) {
8282 0 : printf("cli_close of %s failed (%s)\n",
8283 : fname,
8284 : nt_errstr(status));
8285 0 : goto out;
8286 : }
8287 4 : fnum1 = (uint16_t)-1;
8288 :
8289 : /* Now create the stream. */
8290 4 : status = cli_ntcreate(cli1,
8291 : stream_fname,
8292 : 0,
8293 : FILE_WRITE_DATA,
8294 : 0,
8295 : FILE_SHARE_READ|FILE_SHARE_WRITE,
8296 : FILE_CREATE,
8297 : 0x0,
8298 : 0x0,
8299 : &fnum1,
8300 : NULL);
8301 :
8302 4 : if (!NT_STATUS_IS_OK(status)) {
8303 0 : printf("cli_ntcreate of %s failed (%s)\n",
8304 : stream_fname,
8305 : nt_errstr(status));
8306 0 : goto out;
8307 : }
8308 :
8309 : /* Leave the stream handle open... */
8310 :
8311 : /* POSIX unlink should fail. */
8312 4 : status = cli_posix_unlink(cli2, fname);
8313 4 : if (NT_STATUS_IS_OK(status)) {
8314 0 : printf("cli_posix_unlink of %s succeeded, should have failed\n",
8315 : fname);
8316 0 : goto out;
8317 : }
8318 :
8319 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8320 0 : printf("cli_posix_unlink of %s failed with (%s) "
8321 : "should have been NT_STATUS_SHARING_VIOLATION\n",
8322 : fname,
8323 : nt_errstr(status));
8324 0 : goto out;
8325 : }
8326 :
8327 : /* Close the stream handle. */
8328 4 : status = cli_close(cli1, fnum1);
8329 4 : if (!NT_STATUS_IS_OK(status)) {
8330 0 : printf("cli_close of %s failed (%s)\n",
8331 : stream_fname,
8332 : nt_errstr(status));
8333 0 : goto out;
8334 : }
8335 4 : fnum1 = (uint16_t)-1;
8336 :
8337 : /* POSIX unlink after stream handle closed should succeed. */
8338 4 : status = cli_posix_unlink(cli2, fname);
8339 4 : if (!NT_STATUS_IS_OK(status)) {
8340 0 : printf("cli_posix_unlink of %s failed (%s)\n",
8341 : fname,
8342 : nt_errstr(status));
8343 0 : goto out;
8344 : }
8345 :
8346 4 : printf("POSIX stream delete test passed\n");
8347 4 : correct = true;
8348 :
8349 4 : out:
8350 :
8351 4 : if (fnum1 != (uint16_t)-1) {
8352 0 : cli_close(cli1, fnum1);
8353 0 : fnum1 = (uint16_t)-1;
8354 : }
8355 :
8356 4 : cli_setatr(cli1, fname, 0, 0);
8357 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8358 :
8359 4 : if (!torture_close_connection(cli1)) {
8360 0 : correct = false;
8361 : }
8362 4 : if (!torture_close_connection(cli2)) {
8363 0 : correct = false;
8364 : }
8365 :
8366 4 : TALLOC_FREE(frame);
8367 4 : return correct;
8368 : }
8369 :
8370 : /*
8371 : Test setting EA's are rejected on symlinks.
8372 : */
8373 4 : static bool run_ea_symlink_test(int dummy)
8374 : {
8375 : static struct cli_state *cli;
8376 4 : const char *fname = "posix_file_ea";
8377 4 : const char *sname = "posix_symlink_ea";
8378 4 : const char *ea_name = "testea_name";
8379 4 : const char *ea_value = "testea_value";
8380 4 : uint16_t fnum = (uint16_t)-1;
8381 4 : bool correct = false;
8382 : NTSTATUS status;
8383 : size_t i, num_eas;
8384 4 : struct ea_struct *eas = NULL;
8385 4 : TALLOC_CTX *frame = NULL;
8386 :
8387 4 : frame = talloc_stackframe();
8388 :
8389 4 : printf("Starting EA symlink test\n");
8390 :
8391 4 : if (!torture_open_connection(&cli, 0)) {
8392 0 : TALLOC_FREE(frame);
8393 0 : return false;
8394 : }
8395 :
8396 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8397 :
8398 4 : status = torture_setup_unix_extensions(cli);
8399 4 : if (!NT_STATUS_IS_OK(status)) {
8400 0 : TALLOC_FREE(frame);
8401 0 : return false;
8402 : }
8403 :
8404 4 : cli_setatr(cli, fname, 0, 0);
8405 4 : cli_posix_unlink(cli, fname);
8406 4 : cli_setatr(cli, sname, 0, 0);
8407 4 : cli_posix_unlink(cli, sname);
8408 :
8409 4 : status = cli_ntcreate(cli,
8410 : fname,
8411 : 0,
8412 : READ_CONTROL_ACCESS,
8413 : 0,
8414 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8415 : FILE_CREATE,
8416 : 0x0,
8417 : 0x0,
8418 : &fnum,
8419 : NULL);
8420 :
8421 4 : if (!NT_STATUS_IS_OK(status)) {
8422 0 : printf("cli_ntcreate of %s failed (%s)\n",
8423 : fname,
8424 : nt_errstr(status));
8425 0 : goto out;
8426 : }
8427 :
8428 4 : status = cli_close(cli, fnum);
8429 4 : if (!NT_STATUS_IS_OK(status)) {
8430 0 : printf("close failed (%s)\n",
8431 : nt_errstr(status));
8432 0 : goto out;
8433 : }
8434 4 : fnum = (uint16_t)-1;
8435 :
8436 : /* Set an EA on the path. */
8437 4 : status = cli_set_ea_path(cli,
8438 : fname,
8439 : ea_name,
8440 : ea_value,
8441 4 : strlen(ea_value)+1);
8442 :
8443 4 : if (!NT_STATUS_IS_OK(status)) {
8444 0 : printf("cli_set_ea_path failed (%s)\n",
8445 : nt_errstr(status));
8446 0 : goto out;
8447 : }
8448 :
8449 : /* Now create a symlink. */
8450 4 : status = cli_posix_symlink(cli, fname, sname);
8451 4 : if (!NT_STATUS_IS_OK(status)) {
8452 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8453 : sname,
8454 : fname,
8455 : nt_errstr(status));
8456 0 : goto out;
8457 : }
8458 :
8459 : /* Get the EA list on the path. Should return value set. */
8460 4 : status = cli_get_ea_list_path(cli,
8461 : fname,
8462 : frame,
8463 : &num_eas,
8464 : &eas);
8465 :
8466 4 : if (!NT_STATUS_IS_OK(status)) {
8467 0 : printf("cli_get_ea_list_path failed (%s)\n",
8468 : nt_errstr(status));
8469 0 : goto out;
8470 : }
8471 :
8472 : /* Ensure the EA we set is there. */
8473 4 : for (i=0; i<num_eas; i++) {
8474 8 : if (strcmp(eas[i].name, ea_name) == 0 &&
8475 8 : eas[i].value.length == strlen(ea_value)+1 &&
8476 4 : memcmp(eas[i].value.data,
8477 : ea_value,
8478 4 : eas[i].value.length) == 0) {
8479 4 : break;
8480 : }
8481 : }
8482 :
8483 4 : if (i == num_eas) {
8484 0 : printf("Didn't find EA on pathname %s\n",
8485 : fname);
8486 0 : goto out;
8487 : }
8488 :
8489 4 : num_eas = 0;
8490 4 : TALLOC_FREE(eas);
8491 :
8492 : /* Get the EA list on the symlink. Should return empty list. */
8493 4 : status = cli_get_ea_list_path(cli,
8494 : sname,
8495 : frame,
8496 : &num_eas,
8497 : &eas);
8498 :
8499 4 : if (!NT_STATUS_IS_OK(status)) {
8500 0 : printf("cli_get_ea_list_path failed (%s)\n",
8501 : nt_errstr(status));
8502 0 : goto out;
8503 : }
8504 :
8505 4 : if (num_eas != 0) {
8506 0 : printf("cli_get_ea_list_path failed (%s)\n",
8507 : nt_errstr(status));
8508 0 : goto out;
8509 : }
8510 :
8511 : /* Set an EA on the symlink. Should fail. */
8512 4 : status = cli_set_ea_path(cli,
8513 : sname,
8514 : ea_name,
8515 : ea_value,
8516 4 : strlen(ea_value)+1);
8517 :
8518 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8519 0 : printf("cli_set_ea_path on a symlink gave %s. "
8520 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8521 : nt_errstr(status));
8522 0 : goto out;
8523 : }
8524 :
8525 4 : printf("EA symlink test passed\n");
8526 4 : correct = true;
8527 :
8528 4 : out:
8529 :
8530 4 : if (fnum != (uint16_t)-1) {
8531 0 : cli_close(cli, fnum);
8532 0 : fnum = (uint16_t)-1;
8533 : }
8534 :
8535 4 : cli_setatr(cli, sname, 0, 0);
8536 4 : cli_posix_unlink(cli, sname);
8537 4 : cli_setatr(cli, fname, 0, 0);
8538 4 : cli_posix_unlink(cli, fname);
8539 :
8540 4 : if (!torture_close_connection(cli)) {
8541 0 : correct = false;
8542 : }
8543 :
8544 4 : TALLOC_FREE(frame);
8545 4 : return correct;
8546 : }
8547 :
8548 : /*
8549 : Test POSIX locks are OFD-locks.
8550 : */
8551 4 : static bool run_posix_ofd_lock_test(int dummy)
8552 : {
8553 : static struct cli_state *cli;
8554 4 : const char *fname = "posix_file";
8555 4 : uint16_t fnum1 = (uint16_t)-1;
8556 4 : uint16_t fnum2 = (uint16_t)-1;
8557 4 : bool correct = false;
8558 : NTSTATUS status;
8559 4 : TALLOC_CTX *frame = NULL;
8560 :
8561 4 : frame = talloc_stackframe();
8562 :
8563 4 : printf("Starting POSIX ofd-lock test\n");
8564 :
8565 4 : if (!torture_open_connection(&cli, 0)) {
8566 0 : TALLOC_FREE(frame);
8567 0 : return false;
8568 : }
8569 :
8570 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8571 :
8572 4 : status = torture_setup_unix_extensions(cli);
8573 4 : if (!NT_STATUS_IS_OK(status)) {
8574 0 : TALLOC_FREE(frame);
8575 0 : return false;
8576 : }
8577 :
8578 4 : cli_setatr(cli, fname, 0, 0);
8579 4 : cli_posix_unlink(cli, fname);
8580 :
8581 : /* Open the file twice. */
8582 4 : status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8583 : 0600, &fnum1);
8584 4 : if (!NT_STATUS_IS_OK(status)) {
8585 0 : printf("First POSIX open of %s failed\n", fname);
8586 0 : goto out;
8587 : }
8588 :
8589 4 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8590 4 : if (!NT_STATUS_IS_OK(status)) {
8591 0 : printf("First POSIX open of %s failed\n", fname);
8592 0 : goto out;
8593 : }
8594 :
8595 : /* Set a 0-50 lock on fnum1. */
8596 4 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8597 4 : if (!NT_STATUS_IS_OK(status)) {
8598 0 : printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8599 0 : goto out;
8600 : }
8601 :
8602 : /* Set a 60-100 lock on fnum2. */
8603 4 : status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8604 4 : if (!NT_STATUS_IS_OK(status)) {
8605 0 : printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8606 0 : goto out;
8607 : }
8608 :
8609 : /* close fnum1 - 0-50 lock should go away. */
8610 4 : status = cli_close(cli, fnum1);
8611 4 : if (!NT_STATUS_IS_OK(status)) {
8612 0 : printf("close failed (%s)\n",
8613 : nt_errstr(status));
8614 0 : goto out;
8615 : }
8616 4 : fnum1 = (uint16_t)-1;
8617 :
8618 : /* Change the lock context. */
8619 4 : cli_setpid(cli, cli_getpid(cli) + 1);
8620 :
8621 : /* Re-open fnum1. */
8622 4 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8623 4 : if (!NT_STATUS_IS_OK(status)) {
8624 0 : printf("Third POSIX open of %s failed\n", fname);
8625 0 : goto out;
8626 : }
8627 :
8628 : /* 60-100 lock should still be there. */
8629 4 : status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8630 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8631 0 : printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8632 0 : goto out;
8633 : }
8634 :
8635 : /* 0-50 lock should be gone. */
8636 4 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8637 4 : if (!NT_STATUS_IS_OK(status)) {
8638 0 : printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8639 0 : goto out;
8640 : }
8641 :
8642 4 : printf("POSIX OFD lock test passed\n");
8643 4 : correct = true;
8644 :
8645 4 : out:
8646 :
8647 4 : if (fnum1 != (uint16_t)-1) {
8648 4 : cli_close(cli, fnum1);
8649 4 : fnum1 = (uint16_t)-1;
8650 : }
8651 4 : if (fnum2 != (uint16_t)-1) {
8652 4 : cli_close(cli, fnum2);
8653 4 : fnum2 = (uint16_t)-1;
8654 : }
8655 :
8656 4 : cli_setatr(cli, fname, 0, 0);
8657 4 : cli_posix_unlink(cli, fname);
8658 :
8659 4 : if (!torture_close_connection(cli)) {
8660 0 : correct = false;
8661 : }
8662 :
8663 4 : TALLOC_FREE(frame);
8664 4 : return correct;
8665 : }
8666 :
8667 : struct posix_blocking_state {
8668 : struct tevent_context *ev;
8669 : struct cli_state *cli1;
8670 : uint16_t fnum1;
8671 : struct cli_state *cli2;
8672 : uint16_t fnum2;
8673 : bool gotblocked;
8674 : bool gotecho;
8675 : };
8676 :
8677 : static void posix_blocking_locked(struct tevent_req *subreq);
8678 : static void posix_blocking_gotblocked(struct tevent_req *subreq);
8679 : static void posix_blocking_gotecho(struct tevent_req *subreq);
8680 : static void posix_blocking_unlocked(struct tevent_req *subreq);
8681 :
8682 4 : static struct tevent_req *posix_blocking_send(
8683 : TALLOC_CTX *mem_ctx,
8684 : struct tevent_context *ev,
8685 : struct cli_state *cli1,
8686 : uint16_t fnum1,
8687 : struct cli_state *cli2,
8688 : uint16_t fnum2)
8689 : {
8690 4 : struct tevent_req *req = NULL, *subreq = NULL;
8691 4 : struct posix_blocking_state *state = NULL;
8692 :
8693 4 : req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8694 4 : if (req == NULL) {
8695 0 : return NULL;
8696 : }
8697 4 : state->ev = ev;
8698 4 : state->cli1 = cli1;
8699 4 : state->fnum1 = fnum1;
8700 4 : state->cli2 = cli2;
8701 4 : state->fnum2 = fnum2;
8702 :
8703 12 : subreq = cli_posix_lock_send(
8704 : state,
8705 4 : state->ev,
8706 4 : state->cli1,
8707 4 : state->fnum1,
8708 : 0,
8709 : 1,
8710 : false,
8711 : WRITE_LOCK);
8712 4 : if (tevent_req_nomem(subreq, req)) {
8713 0 : return tevent_req_post(req, ev);
8714 : }
8715 4 : tevent_req_set_callback(subreq, posix_blocking_locked, req);
8716 4 : return req;
8717 : }
8718 :
8719 4 : static void posix_blocking_locked(struct tevent_req *subreq)
8720 : {
8721 4 : struct tevent_req *req = tevent_req_callback_data(
8722 : subreq, struct tevent_req);
8723 4 : struct posix_blocking_state *state = tevent_req_data(
8724 : req, struct posix_blocking_state);
8725 : NTSTATUS status;
8726 :
8727 4 : status = cli_posix_lock_recv(subreq);
8728 4 : TALLOC_FREE(subreq);
8729 4 : if (tevent_req_nterror(req, status)) {
8730 0 : return;
8731 : }
8732 :
8733 4 : subreq = cli_posix_lock_send(
8734 : state,
8735 : state->ev,
8736 : state->cli2,
8737 4 : state->fnum2,
8738 : 0,
8739 : 1,
8740 : true,
8741 : WRITE_LOCK);
8742 4 : if (tevent_req_nomem(subreq, req)) {
8743 0 : return;
8744 : }
8745 4 : tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8746 :
8747 : /* Make sure the blocking request is delivered */
8748 4 : subreq = cli_echo_send(
8749 : state,
8750 : state->ev,
8751 : state->cli2,
8752 : 1,
8753 4 : (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8754 4 : if (tevent_req_nomem(subreq, req)) {
8755 0 : return;
8756 : }
8757 4 : tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8758 : }
8759 :
8760 4 : static void posix_blocking_gotblocked(struct tevent_req *subreq)
8761 : {
8762 4 : struct tevent_req *req = tevent_req_callback_data(
8763 : subreq, struct tevent_req);
8764 4 : struct posix_blocking_state *state = tevent_req_data(
8765 : req, struct posix_blocking_state);
8766 : NTSTATUS status;
8767 :
8768 4 : status = cli_posix_lock_recv(subreq);
8769 4 : TALLOC_FREE(subreq);
8770 4 : if (tevent_req_nterror(req, status)) {
8771 0 : return;
8772 : }
8773 4 : if (!state->gotecho) {
8774 0 : printf("blocked req got through before echo\n");
8775 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8776 0 : return;
8777 : }
8778 4 : tevent_req_done(req);
8779 : }
8780 :
8781 4 : static void posix_blocking_gotecho(struct tevent_req *subreq)
8782 : {
8783 4 : struct tevent_req *req = tevent_req_callback_data(
8784 : subreq, struct tevent_req);
8785 4 : struct posix_blocking_state *state = tevent_req_data(
8786 : req, struct posix_blocking_state);
8787 : NTSTATUS status;
8788 :
8789 4 : status = cli_echo_recv(subreq);
8790 4 : TALLOC_FREE(subreq);
8791 4 : if (tevent_req_nterror(req, status)) {
8792 0 : return;
8793 : }
8794 4 : if (state->gotblocked) {
8795 0 : printf("blocked req got through before echo\n");
8796 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8797 0 : return;
8798 : }
8799 4 : state->gotecho = true;
8800 :
8801 4 : subreq = cli_posix_lock_send(
8802 : state,
8803 : state->ev,
8804 : state->cli1,
8805 4 : state->fnum1,
8806 : 0,
8807 : 1,
8808 : false,
8809 : UNLOCK_LOCK);
8810 4 : if (tevent_req_nomem(subreq, req)) {
8811 0 : return;
8812 : }
8813 4 : tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8814 : }
8815 :
8816 4 : static void posix_blocking_unlocked(struct tevent_req *subreq)
8817 : {
8818 4 : struct tevent_req *req = tevent_req_callback_data(
8819 : subreq, struct tevent_req);
8820 : NTSTATUS status;
8821 :
8822 4 : status = cli_posix_lock_recv(subreq);
8823 4 : TALLOC_FREE(subreq);
8824 4 : if (tevent_req_nterror(req, status)) {
8825 0 : return;
8826 : }
8827 : /* tevent_req_done in posix_blocking_gotlocked */
8828 : }
8829 :
8830 4 : static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8831 : {
8832 4 : return tevent_req_simple_recv_ntstatus(req);
8833 : }
8834 :
8835 4 : static bool run_posix_blocking_lock(int dummy)
8836 : {
8837 4 : struct tevent_context *ev = NULL;
8838 4 : struct cli_state *cli1 = NULL, *cli2 = NULL;
8839 4 : const char *fname = "posix_blocking";
8840 4 : uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8841 4 : struct tevent_req *req = NULL;
8842 : NTSTATUS status;
8843 4 : bool ret = false;
8844 : bool ok;
8845 :
8846 4 : printf("Starting posix blocking lock test\n");
8847 :
8848 4 : ev = samba_tevent_context_init(NULL);
8849 4 : if (ev == NULL) {
8850 0 : return false;
8851 : }
8852 :
8853 4 : ok = torture_open_connection(&cli1, 0);
8854 4 : if (!ok) {
8855 0 : goto fail;
8856 : }
8857 4 : ok = torture_open_connection(&cli2, 0);
8858 4 : if (!ok) {
8859 0 : goto fail;
8860 : }
8861 :
8862 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
8863 :
8864 4 : status = torture_setup_unix_extensions(cli1);
8865 4 : if (!NT_STATUS_IS_OK(status)) {
8866 0 : return false;
8867 : }
8868 :
8869 4 : cli_setatr(cli1, fname, 0, 0);
8870 4 : cli_posix_unlink(cli1, fname);
8871 :
8872 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8873 : 0600, &fnum1);
8874 4 : if (!NT_STATUS_IS_OK(status)) {
8875 0 : printf("First POSIX open of %s failed: %s\n",
8876 : fname,
8877 : nt_errstr(status));
8878 0 : goto fail;
8879 : }
8880 :
8881 4 : status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8882 4 : if (!NT_STATUS_IS_OK(status)) {
8883 0 : printf("Second POSIX open of %s failed: %s\n",
8884 : fname,
8885 : nt_errstr(status));
8886 0 : goto fail;
8887 : }
8888 :
8889 4 : req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
8890 4 : if (req == NULL) {
8891 0 : printf("cli_posix_blocking failed\n");
8892 0 : goto fail;
8893 : }
8894 :
8895 4 : ok = tevent_req_poll_ntstatus(req, ev, &status);
8896 4 : if (!ok) {
8897 0 : printf("tevent_req_poll_ntstatus failed: %s\n",
8898 : nt_errstr(status));
8899 0 : goto fail;
8900 : }
8901 4 : status = posix_blocking_recv(req);
8902 4 : TALLOC_FREE(req);
8903 4 : if (!NT_STATUS_IS_OK(status)) {
8904 0 : printf("posix_blocking_recv returned %s\n",
8905 : nt_errstr(status));
8906 0 : goto fail;
8907 : }
8908 :
8909 4 : ret = true;
8910 4 : fail:
8911 :
8912 4 : if (fnum1 != UINT16_MAX) {
8913 4 : cli_close(cli1, fnum1);
8914 4 : fnum1 = UINT16_MAX;
8915 : }
8916 4 : if (fnum2 != UINT16_MAX) {
8917 4 : cli_close(cli2, fnum2);
8918 4 : fnum2 = UINT16_MAX;
8919 : }
8920 :
8921 4 : if (cli1 != NULL) {
8922 4 : cli_setatr(cli1, fname, 0, 0);
8923 4 : cli_posix_unlink(cli1, fname);
8924 : }
8925 :
8926 4 : ok = true;
8927 :
8928 4 : if (cli1 != NULL) {
8929 4 : ok &= torture_close_connection(cli1);
8930 4 : cli1 = NULL;
8931 : }
8932 4 : if (cli2 != NULL) {
8933 4 : ok &= torture_close_connection(cli2);
8934 4 : cli2 = NULL;
8935 : }
8936 :
8937 4 : if (!ok) {
8938 0 : ret = false;
8939 : }
8940 4 : TALLOC_FREE(ev);
8941 4 : return ret;
8942 : }
8943 :
8944 : /*
8945 : Test POSIX mkdir is case-sensitive.
8946 : */
8947 4 : static bool run_posix_mkdir_test(int dummy)
8948 : {
8949 : static struct cli_state *cli;
8950 4 : const char *fname_foo = "POSIX_foo";
8951 4 : const char *fname_foo_Foo = "POSIX_foo/Foo";
8952 4 : const char *fname_foo_foo = "POSIX_foo/foo";
8953 4 : const char *fname_Foo = "POSIX_Foo";
8954 4 : const char *fname_Foo_Foo = "POSIX_Foo/Foo";
8955 4 : const char *fname_Foo_foo = "POSIX_Foo/foo";
8956 4 : bool correct = false;
8957 : NTSTATUS status;
8958 4 : TALLOC_CTX *frame = NULL;
8959 4 : uint16_t fnum = (uint16_t)-1;
8960 :
8961 4 : frame = talloc_stackframe();
8962 :
8963 4 : printf("Starting POSIX mkdir test\n");
8964 :
8965 4 : if (!torture_open_connection(&cli, 0)) {
8966 0 : TALLOC_FREE(frame);
8967 0 : return false;
8968 : }
8969 :
8970 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8971 :
8972 4 : status = torture_setup_unix_extensions(cli);
8973 4 : if (!NT_STATUS_IS_OK(status)) {
8974 0 : TALLOC_FREE(frame);
8975 0 : return false;
8976 : }
8977 :
8978 4 : cli_posix_rmdir(cli, fname_foo_foo);
8979 4 : cli_posix_rmdir(cli, fname_foo_Foo);
8980 4 : cli_posix_rmdir(cli, fname_foo);
8981 :
8982 4 : cli_posix_rmdir(cli, fname_Foo_foo);
8983 4 : cli_posix_rmdir(cli, fname_Foo_Foo);
8984 4 : cli_posix_rmdir(cli, fname_Foo);
8985 :
8986 : /*
8987 : * Create a file POSIX_foo then try
8988 : * and use it in a directory path by
8989 : * doing mkdir POSIX_foo/bar.
8990 : * The mkdir should fail with
8991 : * NT_STATUS_OBJECT_PATH_NOT_FOUND
8992 : */
8993 :
8994 4 : status = cli_posix_open(cli,
8995 : fname_foo,
8996 : O_RDWR|O_CREAT,
8997 : 0666,
8998 : &fnum);
8999 4 : if (!NT_STATUS_IS_OK(status)) {
9000 0 : printf("cli_posix_open of %s failed error %s\n",
9001 : fname_foo,
9002 : nt_errstr(status));
9003 0 : goto out;
9004 : }
9005 :
9006 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9007 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9008 0 : printf("cli_posix_mkdir of %s should fail with "
9009 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9010 : "%s instead\n",
9011 : fname_foo_foo,
9012 : nt_errstr(status));
9013 0 : goto out;
9014 : }
9015 :
9016 4 : status = cli_close(cli, fnum);
9017 4 : if (!NT_STATUS_IS_OK(status)) {
9018 0 : printf("cli_close failed %s\n", nt_errstr(status));
9019 0 : goto out;
9020 : }
9021 4 : fnum = (uint16_t)-1;
9022 :
9023 4 : status = cli_posix_unlink(cli, fname_foo);
9024 4 : if (!NT_STATUS_IS_OK(status)) {
9025 0 : printf("cli_posix_unlink of %s failed error %s\n",
9026 : fname_foo,
9027 : nt_errstr(status));
9028 0 : goto out;
9029 : }
9030 :
9031 : /*
9032 : * Now we've deleted everything, posix_mkdir, posix_rmdir,
9033 : * posix_open, posix_unlink, on
9034 : * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9035 : * not silently create POSIX_foo/foo.
9036 : */
9037 :
9038 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9039 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9040 0 : printf("cli_posix_mkdir of %s should fail with "
9041 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9042 : "%s instead\n",
9043 : fname_foo_foo,
9044 : nt_errstr(status));
9045 0 : goto out;
9046 : }
9047 :
9048 4 : status = cli_posix_rmdir(cli, fname_foo_foo);
9049 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9050 0 : printf("cli_posix_rmdir of %s should fail with "
9051 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9052 : "%s instead\n",
9053 : fname_foo_foo,
9054 : nt_errstr(status));
9055 0 : goto out;
9056 : }
9057 :
9058 4 : status = cli_posix_open(cli,
9059 : fname_foo_foo,
9060 : O_RDWR|O_CREAT,
9061 : 0666,
9062 : &fnum);
9063 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9064 0 : printf("cli_posix_open of %s should fail with "
9065 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9066 : "%s instead\n",
9067 : fname_foo_foo,
9068 : nt_errstr(status));
9069 0 : goto out;
9070 : }
9071 :
9072 4 : status = cli_posix_unlink(cli, fname_foo_foo);
9073 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9074 0 : printf("cli_posix_unlink of %s should fail with "
9075 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9076 : "%s instead\n",
9077 : fname_foo_foo,
9078 : nt_errstr(status));
9079 0 : goto out;
9080 : }
9081 :
9082 4 : status = cli_posix_mkdir(cli, fname_foo, 0777);
9083 4 : if (!NT_STATUS_IS_OK(status)) {
9084 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo);
9085 0 : goto out;
9086 : }
9087 :
9088 4 : status = cli_posix_mkdir(cli, fname_Foo, 0777);
9089 4 : if (!NT_STATUS_IS_OK(status)) {
9090 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9091 0 : goto out;
9092 : }
9093 :
9094 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9095 4 : if (!NT_STATUS_IS_OK(status)) {
9096 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9097 0 : goto out;
9098 : }
9099 :
9100 4 : status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9101 4 : if (!NT_STATUS_IS_OK(status)) {
9102 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9103 0 : goto out;
9104 : }
9105 :
9106 4 : status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9107 4 : if (!NT_STATUS_IS_OK(status)) {
9108 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9109 0 : goto out;
9110 : }
9111 :
9112 4 : status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9113 4 : if (!NT_STATUS_IS_OK(status)) {
9114 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9115 0 : goto out;
9116 : }
9117 :
9118 4 : printf("POSIX mkdir test passed\n");
9119 4 : correct = true;
9120 :
9121 4 : out:
9122 :
9123 4 : if (fnum != (uint16_t)-1) {
9124 0 : cli_close(cli, fnum);
9125 0 : fnum = (uint16_t)-1;
9126 : }
9127 :
9128 4 : cli_posix_rmdir(cli, fname_foo_foo);
9129 4 : cli_posix_rmdir(cli, fname_foo_Foo);
9130 4 : cli_posix_rmdir(cli, fname_foo);
9131 :
9132 4 : cli_posix_rmdir(cli, fname_Foo_foo);
9133 4 : cli_posix_rmdir(cli, fname_Foo_Foo);
9134 4 : cli_posix_rmdir(cli, fname_Foo);
9135 :
9136 4 : if (!torture_close_connection(cli)) {
9137 0 : correct = false;
9138 : }
9139 :
9140 4 : TALLOC_FREE(frame);
9141 4 : return correct;
9142 : }
9143 :
9144 : struct posix_acl_oplock_state {
9145 : struct tevent_context *ev;
9146 : struct cli_state *cli;
9147 : bool *got_break;
9148 : bool *acl_ret;
9149 : NTSTATUS status;
9150 : };
9151 :
9152 4 : static void posix_acl_oplock_got_break(struct tevent_req *req)
9153 : {
9154 4 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9155 : req, struct posix_acl_oplock_state);
9156 : uint16_t fnum;
9157 : uint8_t level;
9158 : NTSTATUS status;
9159 :
9160 4 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9161 4 : TALLOC_FREE(req);
9162 4 : if (!NT_STATUS_IS_OK(status)) {
9163 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9164 : nt_errstr(status));
9165 0 : return;
9166 : }
9167 4 : *state->got_break = true;
9168 :
9169 4 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9170 : NO_OPLOCK);
9171 4 : if (req == NULL) {
9172 0 : printf("cli_oplock_ack_send failed\n");
9173 0 : return;
9174 : }
9175 : }
9176 :
9177 4 : static void posix_acl_oplock_got_acl(struct tevent_req *req)
9178 : {
9179 4 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9180 : req, struct posix_acl_oplock_state);
9181 4 : size_t ret_size = 0;
9182 4 : char *ret_data = NULL;
9183 :
9184 4 : state->status = cli_posix_getacl_recv(req,
9185 : state,
9186 : &ret_size,
9187 : &ret_data);
9188 :
9189 4 : if (!NT_STATUS_IS_OK(state->status)) {
9190 0 : printf("cli_posix_getacl_recv returned %s\n",
9191 : nt_errstr(state->status));
9192 : }
9193 4 : *state->acl_ret = true;
9194 4 : }
9195 :
9196 4 : static bool run_posix_acl_oplock_test(int dummy)
9197 : {
9198 : struct tevent_context *ev;
9199 : struct cli_state *cli1, *cli2;
9200 : struct tevent_req *oplock_req, *getacl_req;
9201 4 : const char *fname = "posix_acl_oplock";
9202 : uint16_t fnum;
9203 4 : int saved_use_oplocks = use_oplocks;
9204 : NTSTATUS status;
9205 4 : bool correct = true;
9206 4 : bool got_break = false;
9207 4 : bool acl_ret = false;
9208 :
9209 : struct posix_acl_oplock_state *state;
9210 :
9211 4 : printf("starting posix_acl_oplock test\n");
9212 :
9213 4 : if (!torture_open_connection(&cli1, 0)) {
9214 0 : use_level_II_oplocks = false;
9215 0 : use_oplocks = saved_use_oplocks;
9216 0 : return false;
9217 : }
9218 :
9219 4 : if (!torture_open_connection(&cli2, 1)) {
9220 0 : use_level_II_oplocks = false;
9221 0 : use_oplocks = saved_use_oplocks;
9222 0 : return false;
9223 : }
9224 :
9225 : /* Setup posix on cli2 only. */
9226 4 : status = torture_setup_unix_extensions(cli2);
9227 4 : if (!NT_STATUS_IS_OK(status)) {
9228 0 : return false;
9229 : }
9230 :
9231 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9232 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
9233 :
9234 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9235 :
9236 : /* Create the file on the Windows connection. */
9237 4 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9238 : &fnum);
9239 4 : if (!NT_STATUS_IS_OK(status)) {
9240 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9241 0 : return false;
9242 : }
9243 :
9244 4 : status = cli_close(cli1, fnum);
9245 4 : if (!NT_STATUS_IS_OK(status)) {
9246 0 : printf("close1 failed (%s)\n", nt_errstr(status));
9247 0 : return false;
9248 : }
9249 :
9250 4 : cli1->use_oplocks = true;
9251 :
9252 : /* Open with oplock. */
9253 4 : status = cli_ntcreate(cli1,
9254 : fname,
9255 : 0,
9256 : FILE_READ_DATA,
9257 : FILE_ATTRIBUTE_NORMAL,
9258 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9259 : FILE_OPEN,
9260 : 0,
9261 : 0,
9262 : &fnum,
9263 : NULL);
9264 :
9265 4 : if (!NT_STATUS_IS_OK(status)) {
9266 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9267 0 : return false;
9268 : }
9269 :
9270 4 : ev = samba_tevent_context_init(talloc_tos());
9271 4 : if (ev == NULL) {
9272 0 : printf("tevent_context_init failed\n");
9273 0 : return false;
9274 : }
9275 :
9276 4 : state = talloc_zero(ev, struct posix_acl_oplock_state);
9277 4 : if (state == NULL) {
9278 0 : printf("talloc failed\n");
9279 0 : return false;
9280 : }
9281 4 : state->ev = ev;
9282 4 : state->cli = cli1;
9283 4 : state->got_break = &got_break;
9284 4 : state->acl_ret = &acl_ret;
9285 :
9286 4 : oplock_req = cli_smb_oplock_break_waiter_send(
9287 : talloc_tos(), ev, cli1);
9288 4 : if (oplock_req == NULL) {
9289 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
9290 0 : return false;
9291 : }
9292 4 : tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9293 :
9294 : /* Get ACL on POSIX connection - should break oplock. */
9295 4 : getacl_req = cli_posix_getacl_send(talloc_tos(),
9296 : ev,
9297 : cli2,
9298 : fname);
9299 4 : if (getacl_req == NULL) {
9300 0 : printf("cli_posix_getacl_send failed\n");
9301 0 : return false;
9302 : }
9303 4 : tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9304 :
9305 4 : while (!got_break || !acl_ret) {
9306 : int ret;
9307 32 : ret = tevent_loop_once(ev);
9308 32 : if (ret == -1) {
9309 0 : printf("tevent_loop_once failed: %s\n",
9310 0 : strerror(errno));
9311 0 : return false;
9312 : }
9313 : }
9314 :
9315 4 : if (!NT_STATUS_IS_OK(state->status)) {
9316 0 : printf("getacl failed (%s)\n", nt_errstr(state->status));
9317 0 : correct = false;
9318 : }
9319 :
9320 4 : status = cli_close(cli1, fnum);
9321 4 : if (!NT_STATUS_IS_OK(status)) {
9322 0 : printf("close2 failed (%s)\n", nt_errstr(status));
9323 0 : correct = false;
9324 : }
9325 :
9326 4 : status = cli_unlink(cli1,
9327 : fname,
9328 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9329 4 : if (!NT_STATUS_IS_OK(status)) {
9330 0 : printf("unlink failed (%s)\n", nt_errstr(status));
9331 0 : correct = false;
9332 : }
9333 :
9334 4 : if (!torture_close_connection(cli1)) {
9335 0 : correct = false;
9336 : }
9337 4 : if (!torture_close_connection(cli2)) {
9338 0 : correct = false;
9339 : }
9340 :
9341 4 : if (!got_break) {
9342 0 : correct = false;
9343 : }
9344 :
9345 4 : printf("finished posix acl oplock test\n");
9346 :
9347 4 : return correct;
9348 : }
9349 :
9350 4 : static bool run_posix_acl_shareroot_test(int dummy)
9351 : {
9352 : struct cli_state *cli;
9353 : NTSTATUS status;
9354 4 : bool correct = false;
9355 4 : char *posix_acl = NULL;
9356 4 : size_t posix_acl_len = 0;
9357 4 : uint16_t num_file_acls = 0;
9358 4 : uint16_t num_dir_acls = 0;
9359 : uint16_t i;
9360 4 : uint32_t expected_size = 0;
9361 4 : bool got_user = false;
9362 4 : bool got_group = false;
9363 4 : bool got_other = false;
9364 4 : TALLOC_CTX *frame = NULL;
9365 :
9366 4 : frame = talloc_stackframe();
9367 :
9368 4 : printf("starting posix_acl_shareroot test\n");
9369 :
9370 4 : if (!torture_open_connection(&cli, 0)) {
9371 0 : TALLOC_FREE(frame);
9372 0 : return false;
9373 : }
9374 :
9375 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9376 :
9377 4 : status = torture_setup_unix_extensions(cli);
9378 4 : if (!NT_STATUS_IS_OK(status)) {
9379 0 : printf("Failed to setup unix extensions\n");
9380 0 : goto out;
9381 : }
9382 :
9383 : /* Get the POSIX ACL on the root of the share. */
9384 4 : status = cli_posix_getacl(cli,
9385 : ".",
9386 : frame,
9387 : &posix_acl_len,
9388 : &posix_acl);
9389 :
9390 4 : if (!NT_STATUS_IS_OK(status)) {
9391 0 : printf("cli_posix_getacl of '.' failed (%s)\n",
9392 : nt_errstr(status));
9393 0 : goto out;
9394 : }
9395 :
9396 8 : if (posix_acl_len < 6 ||
9397 4 : SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9398 0 : printf("getfacl ., unknown POSIX acl version %u.\n",
9399 0 : (unsigned int)CVAL(posix_acl,0) );
9400 0 : goto out;
9401 : }
9402 :
9403 4 : num_file_acls = SVAL(posix_acl,2);
9404 4 : num_dir_acls = SVAL(posix_acl,4);
9405 4 : expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9406 4 : SMB_POSIX_ACL_ENTRY_SIZE*
9407 4 : (num_file_acls+num_dir_acls);
9408 :
9409 4 : if (posix_acl_len != expected_size) {
9410 0 : printf("incorrect POSIX acl buffer size "
9411 : "(should be %u, was %u).\n",
9412 : (unsigned int)expected_size,
9413 : (unsigned int)posix_acl_len);
9414 0 : goto out;
9415 : }
9416 :
9417 : /*
9418 : * We don't need to know what the ACL's are
9419 : * we just need to know we have at least 3
9420 : * file entries (u,g,o).
9421 : */
9422 :
9423 16 : for (i = 0; i < num_file_acls; i++) {
9424 12 : unsigned char tagtype =
9425 12 : CVAL(posix_acl,
9426 : SMB_POSIX_ACL_HEADER_SIZE+
9427 : (i*SMB_POSIX_ACL_ENTRY_SIZE));
9428 :
9429 12 : switch(tagtype) {
9430 4 : case SMB_POSIX_ACL_USER_OBJ:
9431 4 : got_user = true;
9432 4 : break;
9433 4 : case SMB_POSIX_ACL_GROUP_OBJ:
9434 4 : got_group = true;
9435 4 : break;
9436 4 : case SMB_POSIX_ACL_OTHER:
9437 4 : got_other = true;
9438 4 : break;
9439 0 : default:
9440 0 : break;
9441 : }
9442 : }
9443 :
9444 4 : if (!got_user) {
9445 0 : printf("Missing user entry\n");
9446 0 : goto out;
9447 : }
9448 :
9449 4 : if (!got_group) {
9450 0 : printf("Missing group entry\n");
9451 0 : goto out;
9452 : }
9453 :
9454 4 : if (!got_other) {
9455 0 : printf("Missing other entry\n");
9456 0 : goto out;
9457 : }
9458 :
9459 4 : correct = true;
9460 :
9461 4 : out:
9462 :
9463 4 : if (!torture_close_connection(cli)) {
9464 0 : correct = false;
9465 : }
9466 :
9467 4 : printf("finished posix acl shareroot test\n");
9468 4 : TALLOC_FREE(frame);
9469 :
9470 4 : return correct;
9471 : }
9472 :
9473 : static uint32_t open_attrs_table[] = {
9474 : FILE_ATTRIBUTE_NORMAL,
9475 : FILE_ATTRIBUTE_ARCHIVE,
9476 : FILE_ATTRIBUTE_READONLY,
9477 : FILE_ATTRIBUTE_HIDDEN,
9478 : FILE_ATTRIBUTE_SYSTEM,
9479 :
9480 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9481 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9482 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9483 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9484 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9485 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9486 :
9487 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9488 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9489 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9490 : FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9491 : };
9492 :
9493 : struct trunc_open_results {
9494 : unsigned int num;
9495 : uint32_t init_attr;
9496 : uint32_t trunc_attr;
9497 : uint32_t result_attr;
9498 : };
9499 :
9500 : static struct trunc_open_results attr_results[] = {
9501 : { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9502 : { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9503 : { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9504 : { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9505 : { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9506 : { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9507 : { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9508 : { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9509 : { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9510 : { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9511 : { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9512 : { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9513 : { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9514 : { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9515 : { 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 },
9516 : { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9517 : { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9518 : { 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 },
9519 : { 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 },
9520 : { 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 },
9521 : { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9522 : { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9523 : { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9524 : { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9525 : { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9526 : { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9527 : };
9528 :
9529 0 : static bool run_openattrtest(int dummy)
9530 : {
9531 : static struct cli_state *cli1;
9532 0 : const char *fname = "\\openattr.file";
9533 : uint16_t fnum1;
9534 0 : bool correct = True;
9535 : uint32_t attr;
9536 : unsigned int i, j, k, l;
9537 : NTSTATUS status;
9538 :
9539 0 : printf("starting open attr test\n");
9540 :
9541 0 : if (!torture_open_connection(&cli1, 0)) {
9542 0 : return False;
9543 : }
9544 :
9545 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9546 :
9547 0 : for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9548 0 : cli_setatr(cli1, fname, 0, 0);
9549 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9550 :
9551 0 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9552 : open_attrs_table[i], FILE_SHARE_NONE,
9553 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9554 0 : if (!NT_STATUS_IS_OK(status)) {
9555 0 : printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9556 0 : return False;
9557 : }
9558 :
9559 0 : status = cli_close(cli1, fnum1);
9560 0 : if (!NT_STATUS_IS_OK(status)) {
9561 0 : printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9562 0 : return False;
9563 : }
9564 :
9565 0 : for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9566 0 : status = cli_ntcreate(cli1, fname, 0,
9567 : FILE_READ_DATA|FILE_WRITE_DATA,
9568 : open_attrs_table[j],
9569 : FILE_SHARE_NONE, FILE_OVERWRITE,
9570 : 0, 0, &fnum1, NULL);
9571 0 : if (!NT_STATUS_IS_OK(status)) {
9572 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9573 0 : if (attr_results[l].num == k) {
9574 0 : printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9575 : k, open_attrs_table[i],
9576 : open_attrs_table[j],
9577 : fname, NT_STATUS_V(status), nt_errstr(status));
9578 0 : correct = False;
9579 : }
9580 : }
9581 :
9582 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9583 0 : printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9584 : k, open_attrs_table[i], open_attrs_table[j],
9585 : nt_errstr(status));
9586 0 : correct = False;
9587 : }
9588 : #if 0
9589 : printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9590 : #endif
9591 0 : k++;
9592 0 : continue;
9593 : }
9594 :
9595 0 : status = cli_close(cli1, fnum1);
9596 0 : if (!NT_STATUS_IS_OK(status)) {
9597 0 : printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9598 0 : return False;
9599 : }
9600 :
9601 0 : status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9602 0 : if (!NT_STATUS_IS_OK(status)) {
9603 0 : printf("getatr(2) failed (%s)\n", nt_errstr(status));
9604 0 : return False;
9605 : }
9606 :
9607 : #if 0
9608 : printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9609 : k, open_attrs_table[i], open_attrs_table[j], attr );
9610 : #endif
9611 :
9612 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9613 0 : if (attr_results[l].num == k) {
9614 0 : if (attr != attr_results[l].result_attr ||
9615 0 : open_attrs_table[i] != attr_results[l].init_attr ||
9616 0 : open_attrs_table[j] != attr_results[l].trunc_attr) {
9617 0 : printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9618 : open_attrs_table[i],
9619 : open_attrs_table[j],
9620 : (unsigned int)attr,
9621 : attr_results[l].result_attr);
9622 0 : correct = False;
9623 : }
9624 0 : break;
9625 : }
9626 : }
9627 0 : k++;
9628 : }
9629 : }
9630 :
9631 0 : cli_setatr(cli1, fname, 0, 0);
9632 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9633 :
9634 0 : printf("open attr test %s.\n", correct ? "passed" : "failed");
9635 :
9636 0 : if (!torture_close_connection(cli1)) {
9637 0 : correct = False;
9638 : }
9639 0 : return correct;
9640 : }
9641 :
9642 0 : static NTSTATUS list_fn(struct file_info *finfo,
9643 : const char *name, void *state)
9644 : {
9645 0 : int *matched = (int *)state;
9646 0 : if (matched != NULL) {
9647 0 : *matched += 1;
9648 : }
9649 0 : return NT_STATUS_OK;
9650 : }
9651 :
9652 : /*
9653 : test directory listing speed
9654 : */
9655 5 : static bool run_dirtest(int dummy)
9656 : {
9657 : int i;
9658 : static struct cli_state *cli;
9659 : uint16_t fnum;
9660 : struct timeval core_start;
9661 5 : bool correct = True;
9662 : int matched;
9663 :
9664 5 : printf("starting directory test\n");
9665 :
9666 5 : if (!torture_open_connection(&cli, 0)) {
9667 0 : return False;
9668 : }
9669 :
9670 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9671 :
9672 5 : srandom(0);
9673 505 : for (i=0;i<torture_numops;i++) {
9674 : fstring fname;
9675 500 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9676 500 : if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9677 0 : fprintf(stderr,"Failed to open %s\n", fname);
9678 0 : return False;
9679 : }
9680 500 : cli_close(cli, fnum);
9681 : }
9682 :
9683 5 : core_start = timeval_current();
9684 :
9685 5 : matched = 0;
9686 5 : cli_list(cli, "a*.*", 0, list_fn, &matched);
9687 5 : printf("Matched %d\n", matched);
9688 :
9689 5 : matched = 0;
9690 5 : cli_list(cli, "b*.*", 0, list_fn, &matched);
9691 5 : printf("Matched %d\n", matched);
9692 :
9693 5 : matched = 0;
9694 5 : cli_list(cli, "xyzabc", 0, list_fn, &matched);
9695 5 : printf("Matched %d\n", matched);
9696 :
9697 5 : printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9698 :
9699 5 : srandom(0);
9700 505 : for (i=0;i<torture_numops;i++) {
9701 : fstring fname;
9702 500 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9703 500 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9704 : }
9705 :
9706 5 : if (!torture_close_connection(cli)) {
9707 0 : correct = False;
9708 : }
9709 :
9710 5 : printf("finished dirtest\n");
9711 :
9712 5 : return correct;
9713 : }
9714 :
9715 0 : static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9716 : void *state)
9717 : {
9718 0 : struct cli_state *pcli = (struct cli_state *)state;
9719 : fstring fname;
9720 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9721 :
9722 0 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9723 0 : return NT_STATUS_OK;
9724 :
9725 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9726 0 : if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9727 0 : printf("del_fn: failed to rmdir %s\n,", fname );
9728 : } else {
9729 0 : if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9730 0 : printf("del_fn: failed to unlink %s\n,", fname );
9731 : }
9732 0 : return NT_STATUS_OK;
9733 : }
9734 :
9735 :
9736 : /*
9737 : sees what IOCTLs are supported
9738 : */
9739 5 : bool torture_ioctl_test(int dummy)
9740 : {
9741 : static struct cli_state *cli;
9742 : uint16_t device, function;
9743 : uint16_t fnum;
9744 5 : const char *fname = "\\ioctl.dat";
9745 : DATA_BLOB blob;
9746 : NTSTATUS status;
9747 :
9748 5 : if (!torture_open_connection(&cli, 0)) {
9749 0 : return False;
9750 : }
9751 :
9752 5 : printf("starting ioctl test\n");
9753 :
9754 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9755 :
9756 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9757 5 : if (!NT_STATUS_IS_OK(status)) {
9758 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9759 0 : return False;
9760 : }
9761 :
9762 5 : status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9763 5 : printf("ioctl device info: %s\n", nt_errstr(status));
9764 :
9765 5 : status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9766 5 : printf("ioctl job info: %s\n", nt_errstr(status));
9767 :
9768 1285 : for (device=0;device<0x100;device++) {
9769 1280 : printf("ioctl test with device = 0x%x\n", device);
9770 328960 : for (function=0;function<0x100;function++) {
9771 327680 : uint32_t code = (device<<16) | function;
9772 :
9773 327680 : status = cli_raw_ioctl(cli, fnum, code, &blob);
9774 :
9775 327680 : if (NT_STATUS_IS_OK(status)) {
9776 4 : printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9777 4 : (int)blob.length);
9778 4 : data_blob_free(&blob);
9779 : }
9780 : }
9781 : }
9782 :
9783 5 : if (!torture_close_connection(cli)) {
9784 0 : return False;
9785 : }
9786 :
9787 5 : return True;
9788 : }
9789 :
9790 :
9791 : /*
9792 : tries varients of chkpath
9793 : */
9794 5 : bool torture_chkpath_test(int dummy)
9795 : {
9796 : static struct cli_state *cli;
9797 : uint16_t fnum;
9798 : bool ret;
9799 : NTSTATUS status;
9800 :
9801 5 : if (!torture_open_connection(&cli, 0)) {
9802 0 : return False;
9803 : }
9804 :
9805 5 : printf("starting chkpath test\n");
9806 :
9807 : /* cleanup from an old run */
9808 5 : cli_rmdir(cli, "\\chkpath.dir\\dir2");
9809 5 : cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9810 5 : cli_rmdir(cli, "\\chkpath.dir");
9811 :
9812 5 : status = cli_mkdir(cli, "\\chkpath.dir");
9813 5 : if (!NT_STATUS_IS_OK(status)) {
9814 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
9815 0 : return False;
9816 : }
9817 :
9818 5 : status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9819 5 : if (!NT_STATUS_IS_OK(status)) {
9820 0 : printf("mkdir2 failed : %s\n", nt_errstr(status));
9821 0 : return False;
9822 : }
9823 :
9824 5 : status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9825 : DENY_NONE, &fnum);
9826 5 : if (!NT_STATUS_IS_OK(status)) {
9827 0 : printf("open1 failed (%s)\n", nt_errstr(status));
9828 0 : return False;
9829 : }
9830 5 : cli_close(cli, fnum);
9831 :
9832 5 : status = cli_chkpath(cli, "\\chkpath.dir");
9833 5 : if (!NT_STATUS_IS_OK(status)) {
9834 0 : printf("chkpath1 failed: %s\n", nt_errstr(status));
9835 0 : ret = False;
9836 : }
9837 :
9838 5 : status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9839 5 : if (!NT_STATUS_IS_OK(status)) {
9840 0 : printf("chkpath2 failed: %s\n", nt_errstr(status));
9841 0 : ret = False;
9842 : }
9843 :
9844 5 : status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9845 5 : if (!NT_STATUS_IS_OK(status)) {
9846 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9847 5 : NT_STATUS_NOT_A_DIRECTORY);
9848 : } else {
9849 0 : printf("* chkpath on a file should fail\n");
9850 0 : ret = False;
9851 : }
9852 :
9853 5 : status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9854 5 : if (!NT_STATUS_IS_OK(status)) {
9855 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9856 5 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
9857 : } else {
9858 0 : printf("* chkpath on a non existent file should fail\n");
9859 0 : ret = False;
9860 : }
9861 :
9862 5 : status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9863 5 : if (!NT_STATUS_IS_OK(status)) {
9864 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9865 5 : NT_STATUS_OBJECT_PATH_NOT_FOUND);
9866 : } else {
9867 0 : printf("* chkpath on a non existent component should fail\n");
9868 0 : ret = False;
9869 : }
9870 :
9871 5 : cli_rmdir(cli, "\\chkpath.dir\\dir2");
9872 5 : cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9873 5 : cli_rmdir(cli, "\\chkpath.dir");
9874 :
9875 5 : if (!torture_close_connection(cli)) {
9876 0 : return False;
9877 : }
9878 :
9879 5 : return ret;
9880 : }
9881 :
9882 0 : static bool run_eatest(int dummy)
9883 : {
9884 : static struct cli_state *cli;
9885 0 : const char *fname = "\\eatest.txt";
9886 0 : bool correct = True;
9887 : uint16_t fnum;
9888 : int i;
9889 : size_t num_eas;
9890 0 : struct ea_struct *ea_list = NULL;
9891 0 : TALLOC_CTX *mem_ctx = talloc_init("eatest");
9892 : NTSTATUS status;
9893 :
9894 0 : printf("starting eatest\n");
9895 :
9896 0 : if (!torture_open_connection(&cli, 0)) {
9897 0 : talloc_destroy(mem_ctx);
9898 0 : return False;
9899 : }
9900 :
9901 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9902 :
9903 0 : status = cli_ntcreate(cli, fname, 0,
9904 : FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9905 : FILE_SHARE_NONE, FILE_OVERWRITE_IF,
9906 : 0x4044, 0, &fnum, NULL);
9907 0 : if (!NT_STATUS_IS_OK(status)) {
9908 0 : printf("open failed - %s\n", nt_errstr(status));
9909 0 : talloc_destroy(mem_ctx);
9910 0 : return False;
9911 : }
9912 :
9913 0 : for (i = 0; i < 10; i++) {
9914 : fstring ea_name, ea_val;
9915 :
9916 0 : slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
9917 0 : memset(ea_val, (char)i+1, i+1);
9918 0 : status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
9919 0 : if (!NT_STATUS_IS_OK(status)) {
9920 0 : printf("ea_set of name %s failed - %s\n", ea_name,
9921 : nt_errstr(status));
9922 0 : talloc_destroy(mem_ctx);
9923 0 : return False;
9924 : }
9925 : }
9926 :
9927 0 : cli_close(cli, fnum);
9928 0 : for (i = 0; i < 10; i++) {
9929 : fstring ea_name, ea_val;
9930 :
9931 0 : slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
9932 0 : memset(ea_val, (char)i+1, i+1);
9933 0 : status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
9934 0 : if (!NT_STATUS_IS_OK(status)) {
9935 0 : printf("ea_set of name %s failed - %s\n", ea_name,
9936 : nt_errstr(status));
9937 0 : talloc_destroy(mem_ctx);
9938 0 : return False;
9939 : }
9940 : }
9941 :
9942 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9943 0 : if (!NT_STATUS_IS_OK(status)) {
9944 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
9945 0 : correct = False;
9946 : }
9947 :
9948 0 : printf("num_eas = %d\n", (int)num_eas);
9949 :
9950 0 : if (num_eas != 20) {
9951 0 : printf("Should be 20 EA's stored... failing.\n");
9952 0 : correct = False;
9953 : }
9954 :
9955 0 : for (i = 0; i < num_eas; i++) {
9956 0 : printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9957 0 : dump_data(0, ea_list[i].value.data,
9958 0 : ea_list[i].value.length);
9959 : }
9960 :
9961 : /* Setting EA's to zero length deletes them. Test this */
9962 0 : printf("Now deleting all EA's - case indepenent....\n");
9963 :
9964 : #if 1
9965 0 : cli_set_ea_path(cli, fname, "", "", 0);
9966 : #else
9967 : for (i = 0; i < 20; i++) {
9968 : fstring ea_name;
9969 : slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
9970 : status = cli_set_ea_path(cli, fname, ea_name, "", 0);
9971 : if (!NT_STATUS_IS_OK(status)) {
9972 : printf("ea_set of name %s failed - %s\n", ea_name,
9973 : nt_errstr(status));
9974 : talloc_destroy(mem_ctx);
9975 : return False;
9976 : }
9977 : }
9978 : #endif
9979 :
9980 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9981 0 : if (!NT_STATUS_IS_OK(status)) {
9982 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
9983 0 : correct = False;
9984 : }
9985 :
9986 0 : printf("num_eas = %d\n", (int)num_eas);
9987 0 : for (i = 0; i < num_eas; i++) {
9988 0 : printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9989 0 : dump_data(0, ea_list[i].value.data,
9990 0 : ea_list[i].value.length);
9991 : }
9992 :
9993 0 : if (num_eas != 0) {
9994 0 : printf("deleting EA's failed.\n");
9995 0 : correct = False;
9996 : }
9997 :
9998 : /* Try and delete a non existent EA. */
9999 0 : status = cli_set_ea_path(cli, fname, "foo", "", 0);
10000 0 : if (!NT_STATUS_IS_OK(status)) {
10001 0 : printf("deleting non-existent EA 'foo' should succeed. %s\n",
10002 : nt_errstr(status));
10003 0 : correct = False;
10004 : }
10005 :
10006 0 : talloc_destroy(mem_ctx);
10007 0 : if (!torture_close_connection(cli)) {
10008 0 : correct = False;
10009 : }
10010 :
10011 0 : return correct;
10012 : }
10013 :
10014 0 : static bool run_dirtest1(int dummy)
10015 : {
10016 : int i;
10017 : static struct cli_state *cli;
10018 : uint16_t fnum;
10019 : int num_seen;
10020 0 : bool correct = True;
10021 :
10022 0 : printf("starting directory test\n");
10023 :
10024 0 : if (!torture_open_connection(&cli, 0)) {
10025 0 : return False;
10026 : }
10027 :
10028 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
10029 :
10030 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10031 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10032 0 : cli_rmdir(cli, "\\LISTDIR");
10033 0 : cli_mkdir(cli, "\\LISTDIR");
10034 :
10035 : /* Create 1000 files and 1000 directories. */
10036 0 : for (i=0;i<1000;i++) {
10037 : fstring fname;
10038 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10039 0 : if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10040 : FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10041 : 0, 0, &fnum, NULL))) {
10042 0 : fprintf(stderr,"Failed to open %s\n", fname);
10043 0 : return False;
10044 : }
10045 0 : cli_close(cli, fnum);
10046 : }
10047 0 : for (i=0;i<1000;i++) {
10048 : fstring fname;
10049 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10050 0 : if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10051 0 : fprintf(stderr,"Failed to open %s\n", fname);
10052 0 : return False;
10053 : }
10054 : }
10055 :
10056 : /* Now ensure that doing an old list sees both files and directories. */
10057 0 : num_seen = 0;
10058 0 : cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10059 0 : printf("num_seen = %d\n", num_seen );
10060 : /* We should see 100 files + 1000 directories + . and .. */
10061 0 : if (num_seen != 2002)
10062 0 : correct = False;
10063 :
10064 : /* Ensure if we have the "must have" bits we only see the
10065 : * relevent entries.
10066 : */
10067 0 : num_seen = 0;
10068 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10069 0 : printf("num_seen = %d\n", num_seen );
10070 0 : if (num_seen != 1002)
10071 0 : correct = False;
10072 :
10073 0 : num_seen = 0;
10074 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10075 0 : printf("num_seen = %d\n", num_seen );
10076 0 : if (num_seen != 1000)
10077 0 : correct = False;
10078 :
10079 : /* Delete everything. */
10080 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10081 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10082 0 : cli_rmdir(cli, "\\LISTDIR");
10083 :
10084 : #if 0
10085 : printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10086 : printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10087 : printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10088 : #endif
10089 :
10090 0 : if (!torture_close_connection(cli)) {
10091 0 : correct = False;
10092 : }
10093 :
10094 0 : printf("finished dirtest1\n");
10095 :
10096 0 : return correct;
10097 : }
10098 :
10099 0 : static bool run_error_map_extract(int dummy) {
10100 :
10101 : static struct cli_state *c_dos;
10102 : static struct cli_state *c_nt;
10103 : NTSTATUS status;
10104 :
10105 : uint32_t error;
10106 :
10107 : uint32_t errnum;
10108 : uint8_t errclass;
10109 :
10110 : NTSTATUS nt_status;
10111 :
10112 : fstring user;
10113 :
10114 : /* NT-Error connection */
10115 :
10116 0 : disable_spnego = true;
10117 0 : if (!(c_nt = open_nbt_connection())) {
10118 0 : disable_spnego = false;
10119 0 : return False;
10120 : }
10121 0 : disable_spnego = false;
10122 :
10123 0 : status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10124 : PROTOCOL_NT1);
10125 :
10126 0 : if (!NT_STATUS_IS_OK(status)) {
10127 0 : printf("%s rejected the NT-error negprot (%s)\n", host,
10128 : nt_errstr(status));
10129 0 : cli_shutdown(c_nt);
10130 0 : return False;
10131 : }
10132 :
10133 0 : status = cli_session_setup_anon(c_nt);
10134 0 : if (!NT_STATUS_IS_OK(status)) {
10135 0 : printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10136 0 : return False;
10137 : }
10138 :
10139 : /* DOS-Error connection */
10140 :
10141 0 : disable_spnego = true;
10142 0 : force_dos_errors = true;
10143 0 : if (!(c_dos = open_nbt_connection())) {
10144 0 : disable_spnego = false;
10145 0 : force_dos_errors = false;
10146 0 : return False;
10147 : }
10148 0 : disable_spnego = false;
10149 0 : force_dos_errors = false;
10150 :
10151 0 : status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10152 : PROTOCOL_NT1);
10153 0 : if (!NT_STATUS_IS_OK(status)) {
10154 0 : printf("%s rejected the DOS-error negprot (%s)\n", host,
10155 : nt_errstr(status));
10156 0 : cli_shutdown(c_dos);
10157 0 : return False;
10158 : }
10159 :
10160 0 : status = cli_session_setup_anon(c_dos);
10161 0 : if (!NT_STATUS_IS_OK(status)) {
10162 0 : printf("%s rejected the DOS-error initial session setup (%s)\n",
10163 : host, nt_errstr(status));
10164 0 : return False;
10165 : }
10166 :
10167 0 : c_nt->map_dos_errors = false;
10168 0 : c_dos->map_dos_errors = false;
10169 :
10170 0 : for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10171 0 : struct cli_credentials *user_creds = NULL;
10172 :
10173 0 : fstr_sprintf(user, "%X", error);
10174 :
10175 0 : user_creds = cli_session_creds_init(talloc_tos(),
10176 : user,
10177 : workgroup,
10178 : NULL, /* realm */
10179 : password,
10180 : false, /* use_kerberos */
10181 : false, /* fallback_after_kerberos */
10182 : false, /* use_ccache */
10183 : false); /* password_is_nt_hash */
10184 0 : if (user_creds == NULL) {
10185 0 : printf("cli_session_creds_init(%s) failed\n", user);
10186 0 : return false;
10187 : }
10188 :
10189 0 : status = cli_session_setup_creds(c_nt, user_creds);
10190 0 : if (NT_STATUS_IS_OK(status)) {
10191 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10192 : }
10193 :
10194 : /* Case #1: 32-bit NT errors */
10195 0 : if (!NT_STATUS_IS_DOS(status)) {
10196 0 : nt_status = status;
10197 : } else {
10198 0 : printf("/** Dos error on NT connection! (%s) */\n",
10199 : nt_errstr(status));
10200 0 : nt_status = NT_STATUS(0xc0000000);
10201 : }
10202 :
10203 0 : status = cli_session_setup_creds(c_dos, user_creds);
10204 0 : if (NT_STATUS_IS_OK(status)) {
10205 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10206 : }
10207 :
10208 : /* Case #1: 32-bit NT errors */
10209 0 : if (NT_STATUS_IS_DOS(status)) {
10210 0 : printf("/** NT error on DOS connection! (%s) */\n",
10211 : nt_errstr(status));
10212 0 : errnum = errclass = 0;
10213 : } else {
10214 0 : errclass = NT_STATUS_DOS_CLASS(status);
10215 0 : errnum = NT_STATUS_DOS_CODE(status);
10216 : }
10217 :
10218 0 : if (NT_STATUS_V(nt_status) != error) {
10219 0 : printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10220 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10221 0 : get_nt_error_c_code(talloc_tos(), nt_status));
10222 : }
10223 :
10224 0 : printf("\t{%s,\t%s,\t%s},\n",
10225 : smb_dos_err_class(errclass),
10226 : smb_dos_err_name(errclass, errnum),
10227 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10228 :
10229 0 : TALLOC_FREE(user_creds);
10230 : }
10231 0 : return True;
10232 : }
10233 :
10234 0 : static bool run_sesssetup_bench(int dummy)
10235 : {
10236 : static struct cli_state *c;
10237 0 : const char *fname = "\\file.dat";
10238 : uint16_t fnum;
10239 : NTSTATUS status;
10240 : int i;
10241 :
10242 0 : if (!torture_open_connection(&c, 0)) {
10243 0 : return false;
10244 : }
10245 :
10246 0 : status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10247 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10248 : FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10249 0 : if (!NT_STATUS_IS_OK(status)) {
10250 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10251 0 : return false;
10252 : }
10253 :
10254 0 : for (i=0; i<torture_numops; i++) {
10255 0 : status = cli_session_setup_creds(c, torture_creds);
10256 0 : if (!NT_STATUS_IS_OK(status)) {
10257 0 : d_printf("(%s) cli_session_setup_creds failed: %s\n",
10258 : __location__, nt_errstr(status));
10259 0 : return false;
10260 : }
10261 :
10262 0 : d_printf("\r%d ", (int)cli_state_get_uid(c));
10263 :
10264 0 : status = cli_ulogoff(c);
10265 0 : if (!NT_STATUS_IS_OK(status)) {
10266 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
10267 : __location__, nt_errstr(status));
10268 0 : return false;
10269 : }
10270 : }
10271 :
10272 0 : return true;
10273 : }
10274 :
10275 9 : static bool subst_test(const char *str, const char *user, const char *domain,
10276 : uid_t uid, gid_t gid, const char *expected)
10277 : {
10278 : char *subst;
10279 9 : bool result = true;
10280 :
10281 9 : subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10282 :
10283 9 : if (strcmp(subst, expected) != 0) {
10284 0 : printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10285 : "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10286 : expected);
10287 0 : result = false;
10288 : }
10289 :
10290 9 : TALLOC_FREE(subst);
10291 9 : return result;
10292 : }
10293 :
10294 5 : static void chain1_open_completion(struct tevent_req *req)
10295 : {
10296 : uint16_t fnum;
10297 : NTSTATUS status;
10298 5 : status = cli_openx_recv(req, &fnum);
10299 5 : TALLOC_FREE(req);
10300 :
10301 5 : d_printf("cli_openx_recv returned %s: %d\n",
10302 : nt_errstr(status),
10303 5 : NT_STATUS_IS_OK(status) ? fnum : -1);
10304 5 : }
10305 :
10306 5 : static void chain1_write_completion(struct tevent_req *req)
10307 : {
10308 : size_t written;
10309 : NTSTATUS status;
10310 5 : status = cli_write_andx_recv(req, &written);
10311 5 : TALLOC_FREE(req);
10312 :
10313 10 : d_printf("cli_write_andx_recv returned %s: %d\n",
10314 : nt_errstr(status),
10315 10 : NT_STATUS_IS_OK(status) ? (int)written : -1);
10316 5 : }
10317 :
10318 5 : static void chain1_close_completion(struct tevent_req *req)
10319 : {
10320 : NTSTATUS status;
10321 5 : bool *done = (bool *)tevent_req_callback_data_void(req);
10322 :
10323 5 : status = cli_close_recv(req);
10324 5 : *done = true;
10325 :
10326 5 : TALLOC_FREE(req);
10327 :
10328 5 : d_printf("cli_close returned %s\n", nt_errstr(status));
10329 5 : }
10330 :
10331 5 : static bool run_chain1(int dummy)
10332 : {
10333 : struct cli_state *cli1;
10334 5 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10335 : struct tevent_req *reqs[3], *smbreqs[3];
10336 5 : bool done = false;
10337 5 : const char *str = "foobar";
10338 5 : const char *fname = "\\test_chain";
10339 : NTSTATUS status;
10340 :
10341 5 : printf("starting chain1 test\n");
10342 5 : if (!torture_open_connection(&cli1, 0)) {
10343 0 : return False;
10344 : }
10345 :
10346 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10347 :
10348 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10349 :
10350 5 : reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10351 : O_CREAT|O_RDWR, 0, &smbreqs[0]);
10352 5 : if (reqs[0] == NULL) return false;
10353 5 : tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10354 :
10355 :
10356 5 : reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10357 5 : (const uint8_t *)str, 0, strlen(str)+1,
10358 : smbreqs, 1, &smbreqs[1]);
10359 5 : if (reqs[1] == NULL) return false;
10360 5 : tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10361 :
10362 5 : reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10363 5 : if (reqs[2] == NULL) return false;
10364 5 : tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10365 :
10366 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10367 5 : if (!NT_STATUS_IS_OK(status)) {
10368 0 : return false;
10369 : }
10370 :
10371 40 : while (!done) {
10372 30 : tevent_loop_once(evt);
10373 : }
10374 :
10375 5 : torture_close_connection(cli1);
10376 5 : return True;
10377 : }
10378 :
10379 5 : static void chain2_sesssetup_completion(struct tevent_req *req)
10380 : {
10381 : NTSTATUS status;
10382 5 : status = cli_session_setup_guest_recv(req);
10383 5 : d_printf("sesssetup returned %s\n", nt_errstr(status));
10384 5 : }
10385 :
10386 5 : static void chain2_tcon_completion(struct tevent_req *req)
10387 : {
10388 5 : bool *done = (bool *)tevent_req_callback_data_void(req);
10389 : NTSTATUS status;
10390 5 : status = cli_tcon_andx_recv(req);
10391 5 : d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10392 5 : *done = true;
10393 5 : }
10394 :
10395 5 : static bool run_chain2(int dummy)
10396 : {
10397 : struct cli_state *cli1;
10398 5 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10399 : struct tevent_req *reqs[2], *smbreqs[2];
10400 5 : bool done = false;
10401 : NTSTATUS status;
10402 5 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10403 :
10404 5 : printf("starting chain2 test\n");
10405 5 : status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10406 : port_to_use, SMB_SIGNING_DEFAULT, flags);
10407 5 : if (!NT_STATUS_IS_OK(status)) {
10408 0 : return False;
10409 : }
10410 :
10411 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10412 :
10413 5 : reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10414 : &smbreqs[0]);
10415 5 : if (reqs[0] == NULL) return false;
10416 5 : tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10417 :
10418 5 : reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10419 : "?????", NULL, 0, &smbreqs[1]);
10420 5 : if (reqs[1] == NULL) return false;
10421 5 : tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10422 :
10423 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10424 5 : if (!NT_STATUS_IS_OK(status)) {
10425 0 : return false;
10426 : }
10427 :
10428 35 : while (!done) {
10429 25 : tevent_loop_once(evt);
10430 : }
10431 :
10432 5 : torture_close_connection(cli1);
10433 5 : return True;
10434 : }
10435 :
10436 :
10437 : struct torture_createdel_state {
10438 : struct tevent_context *ev;
10439 : struct cli_state *cli;
10440 : };
10441 :
10442 : static void torture_createdel_created(struct tevent_req *subreq);
10443 : static void torture_createdel_closed(struct tevent_req *subreq);
10444 :
10445 0 : static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10446 : struct tevent_context *ev,
10447 : struct cli_state *cli,
10448 : const char *name)
10449 : {
10450 : struct tevent_req *req, *subreq;
10451 : struct torture_createdel_state *state;
10452 :
10453 0 : req = tevent_req_create(mem_ctx, &state,
10454 : struct torture_createdel_state);
10455 0 : if (req == NULL) {
10456 0 : return NULL;
10457 : }
10458 0 : state->ev = ev;
10459 0 : state->cli = cli;
10460 :
10461 0 : subreq = cli_ntcreate_send(
10462 : state, ev, cli, name, 0,
10463 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10464 : FILE_ATTRIBUTE_NORMAL,
10465 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10466 : FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10467 : SMB2_IMPERSONATION_IMPERSONATION, 0);
10468 :
10469 0 : if (tevent_req_nomem(subreq, req)) {
10470 0 : return tevent_req_post(req, ev);
10471 : }
10472 0 : tevent_req_set_callback(subreq, torture_createdel_created, req);
10473 0 : return req;
10474 : }
10475 :
10476 0 : static void torture_createdel_created(struct tevent_req *subreq)
10477 : {
10478 0 : struct tevent_req *req = tevent_req_callback_data(
10479 : subreq, struct tevent_req);
10480 0 : struct torture_createdel_state *state = tevent_req_data(
10481 : req, struct torture_createdel_state);
10482 : NTSTATUS status;
10483 : uint16_t fnum;
10484 :
10485 0 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
10486 0 : TALLOC_FREE(subreq);
10487 0 : if (tevent_req_nterror(req, status)) {
10488 0 : DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10489 : nt_errstr(status)));
10490 0 : return;
10491 : }
10492 :
10493 0 : subreq = cli_close_send(state, state->ev, state->cli, fnum);
10494 0 : if (tevent_req_nomem(subreq, req)) {
10495 0 : return;
10496 : }
10497 0 : tevent_req_set_callback(subreq, torture_createdel_closed, req);
10498 : }
10499 :
10500 0 : static void torture_createdel_closed(struct tevent_req *subreq)
10501 : {
10502 0 : struct tevent_req *req = tevent_req_callback_data(
10503 : subreq, struct tevent_req);
10504 : NTSTATUS status;
10505 :
10506 0 : status = cli_close_recv(subreq);
10507 0 : if (tevent_req_nterror(req, status)) {
10508 0 : DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10509 0 : return;
10510 : }
10511 0 : tevent_req_done(req);
10512 : }
10513 :
10514 0 : static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10515 : {
10516 0 : return tevent_req_simple_recv_ntstatus(req);
10517 : }
10518 :
10519 : struct torture_createdels_state {
10520 : struct tevent_context *ev;
10521 : struct cli_state *cli;
10522 : const char *base_name;
10523 : int sent;
10524 : int received;
10525 : int num_files;
10526 : struct tevent_req **reqs;
10527 : };
10528 :
10529 : static void torture_createdels_done(struct tevent_req *subreq);
10530 :
10531 0 : static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10532 : struct tevent_context *ev,
10533 : struct cli_state *cli,
10534 : const char *base_name,
10535 : int num_parallel,
10536 : int num_files)
10537 : {
10538 : struct tevent_req *req;
10539 : struct torture_createdels_state *state;
10540 : int i;
10541 :
10542 0 : req = tevent_req_create(mem_ctx, &state,
10543 : struct torture_createdels_state);
10544 0 : if (req == NULL) {
10545 0 : return NULL;
10546 : }
10547 0 : state->ev = ev;
10548 0 : state->cli = cli;
10549 0 : state->base_name = talloc_strdup(state, base_name);
10550 0 : if (tevent_req_nomem(state->base_name, req)) {
10551 0 : return tevent_req_post(req, ev);
10552 : }
10553 0 : state->num_files = MAX(num_parallel, num_files);
10554 0 : state->sent = 0;
10555 0 : state->received = 0;
10556 :
10557 0 : state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10558 0 : if (tevent_req_nomem(state->reqs, req)) {
10559 0 : return tevent_req_post(req, ev);
10560 : }
10561 :
10562 0 : for (i=0; i<num_parallel; i++) {
10563 : char *name;
10564 :
10565 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10566 0 : state->sent);
10567 0 : if (tevent_req_nomem(name, req)) {
10568 0 : return tevent_req_post(req, ev);
10569 : }
10570 0 : state->reqs[i] = torture_createdel_send(
10571 0 : state->reqs, state->ev, state->cli, name);
10572 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10573 0 : return tevent_req_post(req, ev);
10574 : }
10575 0 : name = talloc_move(state->reqs[i], &name);
10576 0 : tevent_req_set_callback(state->reqs[i],
10577 : torture_createdels_done, req);
10578 0 : state->sent += 1;
10579 : }
10580 0 : return req;
10581 : }
10582 :
10583 0 : static void torture_createdels_done(struct tevent_req *subreq)
10584 : {
10585 0 : struct tevent_req *req = tevent_req_callback_data(
10586 : subreq, struct tevent_req);
10587 0 : struct torture_createdels_state *state = tevent_req_data(
10588 : req, struct torture_createdels_state);
10589 0 : size_t num_parallel = talloc_array_length(state->reqs);
10590 : NTSTATUS status;
10591 : char *name;
10592 : int i;
10593 :
10594 0 : status = torture_createdel_recv(subreq);
10595 0 : if (!NT_STATUS_IS_OK(status)){
10596 0 : DEBUG(10, ("torture_createdel_recv returned %s\n",
10597 : nt_errstr(status)));
10598 0 : TALLOC_FREE(subreq);
10599 0 : tevent_req_nterror(req, status);
10600 0 : return;
10601 : }
10602 :
10603 0 : for (i=0; i<num_parallel; i++) {
10604 0 : if (subreq == state->reqs[i]) {
10605 0 : break;
10606 : }
10607 : }
10608 0 : if (i == num_parallel) {
10609 0 : DEBUG(10, ("received something we did not send\n"));
10610 0 : tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10611 0 : return;
10612 : }
10613 0 : TALLOC_FREE(state->reqs[i]);
10614 :
10615 0 : if (state->sent >= state->num_files) {
10616 0 : tevent_req_done(req);
10617 0 : return;
10618 : }
10619 :
10620 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10621 : state->sent);
10622 0 : if (tevent_req_nomem(name, req)) {
10623 0 : return;
10624 : }
10625 0 : state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10626 : state->cli, name);
10627 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10628 0 : return;
10629 : }
10630 0 : name = talloc_move(state->reqs[i], &name);
10631 0 : tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10632 0 : state->sent += 1;
10633 : }
10634 :
10635 0 : static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10636 : {
10637 0 : return tevent_req_simple_recv_ntstatus(req);
10638 : }
10639 :
10640 : struct swallow_notify_state {
10641 : struct tevent_context *ev;
10642 : struct cli_state *cli;
10643 : uint16_t fnum;
10644 : uint32_t completion_filter;
10645 : bool recursive;
10646 : bool (*fn)(uint32_t action, const char *name, void *priv);
10647 : void *priv;
10648 : };
10649 :
10650 : static void swallow_notify_done(struct tevent_req *subreq);
10651 :
10652 0 : static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10653 : struct tevent_context *ev,
10654 : struct cli_state *cli,
10655 : uint16_t fnum,
10656 : uint32_t completion_filter,
10657 : bool recursive,
10658 : bool (*fn)(uint32_t action,
10659 : const char *name,
10660 : void *priv),
10661 : void *priv)
10662 : {
10663 : struct tevent_req *req, *subreq;
10664 : struct swallow_notify_state *state;
10665 :
10666 0 : req = tevent_req_create(mem_ctx, &state,
10667 : struct swallow_notify_state);
10668 0 : if (req == NULL) {
10669 0 : return NULL;
10670 : }
10671 0 : state->ev = ev;
10672 0 : state->cli = cli;
10673 0 : state->fnum = fnum;
10674 0 : state->completion_filter = completion_filter;
10675 0 : state->recursive = recursive;
10676 0 : state->fn = fn;
10677 0 : state->priv = priv;
10678 :
10679 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10680 0 : 0xffff, state->completion_filter,
10681 0 : state->recursive);
10682 0 : if (tevent_req_nomem(subreq, req)) {
10683 0 : return tevent_req_post(req, ev);
10684 : }
10685 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10686 0 : return req;
10687 : }
10688 :
10689 0 : static void swallow_notify_done(struct tevent_req *subreq)
10690 : {
10691 0 : struct tevent_req *req = tevent_req_callback_data(
10692 : subreq, struct tevent_req);
10693 0 : struct swallow_notify_state *state = tevent_req_data(
10694 : req, struct swallow_notify_state);
10695 : NTSTATUS status;
10696 : uint32_t i, num_changes;
10697 : struct notify_change *changes;
10698 :
10699 0 : status = cli_notify_recv(subreq, state, &num_changes, &changes);
10700 0 : TALLOC_FREE(subreq);
10701 0 : if (!NT_STATUS_IS_OK(status)) {
10702 0 : DEBUG(10, ("cli_notify_recv returned %s\n",
10703 : nt_errstr(status)));
10704 0 : tevent_req_nterror(req, status);
10705 0 : return;
10706 : }
10707 :
10708 0 : for (i=0; i<num_changes; i++) {
10709 0 : state->fn(changes[i].action, changes[i].name, state->priv);
10710 : }
10711 0 : TALLOC_FREE(changes);
10712 :
10713 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10714 : 0xffff, state->completion_filter,
10715 0 : state->recursive);
10716 0 : if (tevent_req_nomem(subreq, req)) {
10717 0 : return;
10718 : }
10719 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10720 : }
10721 :
10722 0 : static bool print_notifies(uint32_t action, const char *name, void *priv)
10723 : {
10724 0 : if (DEBUGLEVEL > 5) {
10725 0 : d_printf("%d %s\n", (int)action, name);
10726 : }
10727 0 : return true;
10728 : }
10729 :
10730 0 : static void notify_bench_done(struct tevent_req *req)
10731 : {
10732 0 : int *num_finished = (int *)tevent_req_callback_data_void(req);
10733 0 : *num_finished += 1;
10734 0 : }
10735 :
10736 0 : static bool run_notify_bench(int dummy)
10737 : {
10738 0 : const char *dname = "\\notify-bench";
10739 : struct tevent_context *ev;
10740 : NTSTATUS status;
10741 : uint16_t dnum;
10742 : struct tevent_req *req1;
10743 0 : struct tevent_req *req2 = NULL;
10744 : int i, num_unc_names;
10745 0 : int num_finished = 0;
10746 :
10747 0 : printf("starting notify-bench test\n");
10748 :
10749 0 : if (use_multishare_conn) {
10750 : char **unc_list;
10751 0 : unc_list = file_lines_load(multishare_conn_fname,
10752 : &num_unc_names, 0, NULL);
10753 0 : if (!unc_list || num_unc_names <= 0) {
10754 0 : d_printf("Failed to load unc names list from '%s'\n",
10755 : multishare_conn_fname);
10756 0 : return false;
10757 : }
10758 0 : TALLOC_FREE(unc_list);
10759 : } else {
10760 0 : num_unc_names = 1;
10761 : }
10762 :
10763 0 : ev = samba_tevent_context_init(talloc_tos());
10764 0 : if (ev == NULL) {
10765 0 : d_printf("tevent_context_init failed\n");
10766 0 : return false;
10767 : }
10768 :
10769 0 : for (i=0; i<num_unc_names; i++) {
10770 : struct cli_state *cli;
10771 : char *base_fname;
10772 :
10773 0 : base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10774 : dname, i);
10775 0 : if (base_fname == NULL) {
10776 0 : return false;
10777 : }
10778 :
10779 0 : if (!torture_open_connection(&cli, i)) {
10780 0 : return false;
10781 : }
10782 :
10783 0 : status = cli_ntcreate(cli, dname, 0,
10784 : MAXIMUM_ALLOWED_ACCESS,
10785 : 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10786 : FILE_SHARE_DELETE,
10787 : FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10788 : &dnum, NULL);
10789 :
10790 0 : if (!NT_STATUS_IS_OK(status)) {
10791 0 : d_printf("Could not create %s: %s\n", dname,
10792 : nt_errstr(status));
10793 0 : return false;
10794 : }
10795 :
10796 0 : req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10797 : FILE_NOTIFY_CHANGE_FILE_NAME |
10798 : FILE_NOTIFY_CHANGE_DIR_NAME |
10799 : FILE_NOTIFY_CHANGE_ATTRIBUTES |
10800 : FILE_NOTIFY_CHANGE_LAST_WRITE,
10801 : false, print_notifies, NULL);
10802 0 : if (req1 == NULL) {
10803 0 : d_printf("Could not create notify request\n");
10804 0 : return false;
10805 : }
10806 :
10807 0 : req2 = torture_createdels_send(talloc_tos(), ev, cli,
10808 : base_fname, 10, torture_numops);
10809 0 : if (req2 == NULL) {
10810 0 : d_printf("Could not create createdels request\n");
10811 0 : return false;
10812 : }
10813 0 : TALLOC_FREE(base_fname);
10814 :
10815 0 : tevent_req_set_callback(req2, notify_bench_done,
10816 : &num_finished);
10817 : }
10818 :
10819 0 : while (num_finished < num_unc_names) {
10820 : int ret;
10821 0 : ret = tevent_loop_once(ev);
10822 0 : if (ret != 0) {
10823 0 : d_printf("tevent_loop_once failed\n");
10824 0 : return false;
10825 : }
10826 : }
10827 :
10828 0 : if (!tevent_req_poll(req2, ev)) {
10829 0 : d_printf("tevent_req_poll failed\n");
10830 : }
10831 :
10832 0 : status = torture_createdels_recv(req2);
10833 0 : d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10834 :
10835 0 : return true;
10836 : }
10837 :
10838 0 : static bool run_mangle1(int dummy)
10839 : {
10840 : struct cli_state *cli;
10841 0 : const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10842 : uint16_t fnum;
10843 : fstring alt_name;
10844 : NTSTATUS status;
10845 : time_t change_time, access_time, write_time;
10846 : off_t size;
10847 : uint32_t attr;
10848 :
10849 0 : printf("starting mangle1 test\n");
10850 0 : if (!torture_open_connection(&cli, 0)) {
10851 0 : return False;
10852 : }
10853 :
10854 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
10855 :
10856 0 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10857 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10858 : 0, 0, &fnum, NULL);
10859 0 : if (!NT_STATUS_IS_OK(status)) {
10860 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10861 0 : return false;
10862 : }
10863 0 : cli_close(cli, fnum);
10864 :
10865 0 : status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10866 0 : if (!NT_STATUS_IS_OK(status)) {
10867 0 : d_printf("cli_qpathinfo_alt_name failed: %s\n",
10868 : nt_errstr(status));
10869 0 : return false;
10870 : }
10871 0 : d_printf("alt_name: %s\n", alt_name);
10872 :
10873 0 : status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10874 0 : if (!NT_STATUS_IS_OK(status)) {
10875 0 : d_printf("cli_openx(%s) failed: %s\n", alt_name,
10876 : nt_errstr(status));
10877 0 : return false;
10878 : }
10879 0 : cli_close(cli, fnum);
10880 :
10881 0 : status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10882 : &write_time, &size, &attr);
10883 0 : if (!NT_STATUS_IS_OK(status)) {
10884 0 : d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10885 : nt_errstr(status));
10886 0 : return false;
10887 : }
10888 :
10889 0 : return true;
10890 : }
10891 :
10892 2 : static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
10893 : const char *mask,
10894 : void *state)
10895 : {
10896 2 : if (f->short_name == NULL) {
10897 2 : return NT_STATUS_OK;
10898 : }
10899 :
10900 0 : if (strlen(f->short_name) == 0) {
10901 0 : return NT_STATUS_OK;
10902 : }
10903 :
10904 0 : printf("unexpected shortname: %s\n", f->short_name);
10905 :
10906 0 : return NT_STATUS_OBJECT_NAME_INVALID;
10907 : }
10908 :
10909 2 : static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
10910 : const char *mask,
10911 : void *state)
10912 : {
10913 2 : char *name = state;
10914 :
10915 2 : printf("name: %s\n", f->name);
10916 2 : fstrcpy(name, f->name);
10917 2 : return NT_STATUS_OK;
10918 : }
10919 :
10920 2 : static bool run_mangle_illegal(int dummy)
10921 : {
10922 2 : struct cli_state *cli = NULL;
10923 2 : struct cli_state *cli_posix = NULL;
10924 2 : const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
10925 2 : const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
10926 2 : char *mangled_path = NULL;
10927 : uint16_t fnum;
10928 : fstring name;
10929 : fstring alt_name;
10930 : NTSTATUS status;
10931 :
10932 2 : printf("starting mangle-illegal test\n");
10933 :
10934 2 : if (!torture_open_connection(&cli, 0)) {
10935 0 : return False;
10936 : }
10937 :
10938 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
10939 :
10940 2 : if (!torture_open_connection(&cli_posix, 0)) {
10941 0 : return false;
10942 : }
10943 :
10944 2 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
10945 :
10946 2 : status = torture_setup_unix_extensions(cli_posix);
10947 2 : if (!NT_STATUS_IS_OK(status)) {
10948 0 : return false;
10949 : }
10950 :
10951 2 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10952 2 : status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
10953 2 : if (!NT_STATUS_IS_OK(status)) {
10954 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
10955 0 : return False;
10956 : }
10957 :
10958 : /*
10959 : * Create a file with illegal NTFS characters and test that we
10960 : * get a usable mangled name
10961 : */
10962 :
10963 2 : cli_setatr(cli_posix, illegal_fname, 0, 0);
10964 2 : cli_posix_unlink(cli_posix, illegal_fname);
10965 :
10966 2 : status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
10967 : 0600, &fnum);
10968 2 : if (!NT_STATUS_IS_OK(status)) {
10969 0 : printf("POSIX create of %s failed (%s)\n",
10970 : illegal_fname, nt_errstr(status));
10971 0 : return false;
10972 : }
10973 :
10974 2 : status = cli_close(cli_posix, fnum);
10975 2 : if (!NT_STATUS_IS_OK(status)) {
10976 0 : printf("close failed (%s)\n", nt_errstr(status));
10977 0 : return false;
10978 : }
10979 :
10980 2 : status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
10981 2 : if (!NT_STATUS_IS_OK(status)) {
10982 0 : d_printf("cli_list failed: %s\n", nt_errstr(status));
10983 0 : return false;
10984 : }
10985 :
10986 2 : mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
10987 2 : if (mangled_path == NULL) {
10988 0 : return false;
10989 : }
10990 :
10991 2 : status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
10992 2 : if (!NT_STATUS_IS_OK(status)) {
10993 0 : d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
10994 0 : TALLOC_FREE(mangled_path);
10995 0 : return false;
10996 : }
10997 2 : TALLOC_FREE(mangled_path);
10998 2 : cli_close(cli, fnum);
10999 :
11000 2 : cli_setatr(cli_posix, illegal_fname, 0, 0);
11001 2 : cli_posix_unlink(cli_posix, illegal_fname);
11002 :
11003 : /*
11004 : * Create a file with a long name and check that we got *no* short name.
11005 : */
11006 :
11007 2 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11008 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11009 : 0, 0, &fnum, NULL);
11010 2 : if (!NT_STATUS_IS_OK(status)) {
11011 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11012 0 : return false;
11013 : }
11014 2 : cli_close(cli, fnum);
11015 :
11016 2 : status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11017 2 : if (!NT_STATUS_IS_OK(status)) {
11018 0 : d_printf("cli_list failed\n");
11019 0 : return false;
11020 : }
11021 :
11022 2 : cli_unlink(cli, fname, 0);
11023 2 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11024 :
11025 2 : if (!torture_close_connection(cli_posix)) {
11026 0 : return false;
11027 : }
11028 :
11029 2 : if (!torture_close_connection(cli)) {
11030 0 : return false;
11031 : }
11032 :
11033 2 : return true;
11034 : }
11035 :
11036 0 : static size_t null_source(uint8_t *buf, size_t n, void *priv)
11037 : {
11038 0 : size_t *to_pull = (size_t *)priv;
11039 0 : size_t thistime = *to_pull;
11040 :
11041 0 : thistime = MIN(thistime, n);
11042 0 : if (thistime == 0) {
11043 0 : return 0;
11044 : }
11045 :
11046 0 : memset(buf, 0, thistime);
11047 0 : *to_pull -= thistime;
11048 0 : return thistime;
11049 : }
11050 :
11051 0 : static bool run_windows_write(int dummy)
11052 : {
11053 : struct cli_state *cli1;
11054 : uint16_t fnum;
11055 : int i;
11056 0 : bool ret = false;
11057 0 : const char *fname = "\\writetest.txt";
11058 : struct timeval start_time;
11059 : double seconds;
11060 : double kbytes;
11061 : NTSTATUS status;
11062 :
11063 0 : printf("starting windows_write test\n");
11064 0 : if (!torture_open_connection(&cli1, 0)) {
11065 0 : return False;
11066 : }
11067 :
11068 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11069 0 : if (!NT_STATUS_IS_OK(status)) {
11070 0 : printf("open failed (%s)\n", nt_errstr(status));
11071 0 : return False;
11072 : }
11073 :
11074 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
11075 :
11076 0 : start_time = timeval_current();
11077 :
11078 0 : for (i=0; i<torture_numops; i++) {
11079 0 : uint8_t c = 0;
11080 0 : off_t start = i * torture_blocksize;
11081 0 : size_t to_pull = torture_blocksize - 1;
11082 :
11083 0 : status = cli_writeall(cli1, fnum, 0, &c,
11084 0 : start + torture_blocksize - 1, 1, NULL);
11085 0 : if (!NT_STATUS_IS_OK(status)) {
11086 0 : printf("cli_write failed: %s\n", nt_errstr(status));
11087 0 : goto fail;
11088 : }
11089 :
11090 0 : status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11091 : null_source, &to_pull);
11092 0 : if (!NT_STATUS_IS_OK(status)) {
11093 0 : printf("cli_push returned: %s\n", nt_errstr(status));
11094 0 : goto fail;
11095 : }
11096 : }
11097 :
11098 0 : seconds = timeval_elapsed(&start_time);
11099 0 : kbytes = (double)torture_blocksize * torture_numops;
11100 0 : kbytes /= 1024;
11101 :
11102 0 : printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11103 0 : (double)seconds, (int)(kbytes/seconds));
11104 :
11105 0 : ret = true;
11106 0 : fail:
11107 0 : cli_close(cli1, fnum);
11108 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11109 0 : torture_close_connection(cli1);
11110 0 : return ret;
11111 : }
11112 :
11113 64 : static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11114 : {
11115 64 : size_t max_pdu = 0x1FFFF;
11116 :
11117 64 : if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11118 32 : max_pdu = 0xFFFFFF;
11119 : }
11120 :
11121 64 : if (smb1cli_conn_signing_is_active(cli->conn)) {
11122 32 : max_pdu = 0x1FFFF;
11123 : }
11124 :
11125 64 : if (smb1cli_conn_encryption_on(cli->conn)) {
11126 16 : max_pdu = CLI_BUFFER_SIZE;
11127 : }
11128 :
11129 64 : if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11130 8 : len_requested &= 0xFFFF;
11131 : }
11132 :
11133 64 : return MIN(len_requested,
11134 : max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11135 : }
11136 :
11137 64 : static bool check_read_call(struct cli_state *cli,
11138 : uint16_t fnum,
11139 : uint8_t *buf,
11140 : size_t len_requested)
11141 : {
11142 : NTSTATUS status;
11143 64 : struct tevent_req *subreq = NULL;
11144 64 : ssize_t len_read = 0;
11145 64 : size_t len_expected = 0;
11146 64 : struct tevent_context *ev = NULL;
11147 :
11148 64 : ev = samba_tevent_context_init(talloc_tos());
11149 64 : if (ev == NULL) {
11150 0 : return false;
11151 : }
11152 :
11153 64 : subreq = cli_read_andx_send(talloc_tos(),
11154 : ev,
11155 : cli,
11156 : fnum,
11157 : 0,
11158 : len_requested);
11159 :
11160 64 : if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11161 0 : return false;
11162 : }
11163 :
11164 64 : status = cli_read_andx_recv(subreq, &len_read, &buf);
11165 64 : if (!NT_STATUS_IS_OK(status)) {
11166 0 : d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11167 0 : return false;
11168 : }
11169 :
11170 64 : TALLOC_FREE(subreq);
11171 64 : TALLOC_FREE(ev);
11172 :
11173 64 : len_expected = calc_expected_return(cli, len_requested);
11174 :
11175 64 : if (len_expected > 0x10000 && len_read == 0x10000) {
11176 : /* Windows servers only return a max of 0x10000,
11177 : doesn't matter if you set CAP_LARGE_READX in
11178 : the client sessionsetupX call or not. */
11179 12 : d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11180 : (unsigned int)len_requested);
11181 52 : } else if (len_read != len_expected) {
11182 0 : d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11183 : (unsigned int)len_requested,
11184 : (unsigned int)len_read,
11185 : (unsigned int)len_expected);
11186 0 : return false;
11187 : } else {
11188 52 : d_printf("Correct read reply.\n");
11189 : }
11190 :
11191 64 : return true;
11192 : }
11193 :
11194 : /* Test large readX variants. */
11195 8 : static bool large_readx_tests(struct cli_state *cli,
11196 : uint16_t fnum,
11197 : uint8_t *buf)
11198 : {
11199 : /* A read of 0xFFFF0001 should *always* return 1 byte. */
11200 8 : if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11201 0 : return false;
11202 : }
11203 : /* A read of 0x10000 should return 0x10000 bytes. */
11204 8 : if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11205 0 : return false;
11206 : }
11207 : /* A read of 0x10000 should return 0x10001 bytes. */
11208 8 : if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11209 0 : return false;
11210 : }
11211 : /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11212 : the requested number of bytes. */
11213 8 : if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11214 0 : return false;
11215 : }
11216 : /* A read of 1MB should return 1MB bytes (on Samba). */
11217 8 : if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11218 0 : return false;
11219 : }
11220 :
11221 8 : if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11222 0 : return false;
11223 : }
11224 8 : if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11225 0 : return false;
11226 : }
11227 8 : if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11228 0 : return false;
11229 : }
11230 8 : return true;
11231 : }
11232 :
11233 5 : static bool run_large_readx(int dummy)
11234 : {
11235 5 : uint8_t *buf = NULL;
11236 5 : struct cli_state *cli1 = NULL;
11237 5 : struct cli_state *cli2 = NULL;
11238 5 : bool correct = false;
11239 5 : const char *fname = "\\large_readx.dat";
11240 : NTSTATUS status;
11241 5 : uint16_t fnum1 = UINT16_MAX;
11242 5 : uint32_t normal_caps = 0;
11243 5 : size_t file_size = 20*1024*1024;
11244 5 : TALLOC_CTX *frame = talloc_stackframe();
11245 : size_t i;
11246 : struct {
11247 : const char *name;
11248 : enum smb_signing_setting signing_setting;
11249 : enum protocol_types protocol;
11250 5 : } runs[] = {
11251 : {
11252 : .name = "NT1",
11253 : .signing_setting = SMB_SIGNING_IF_REQUIRED,
11254 : .protocol = PROTOCOL_NT1,
11255 : },{
11256 : .name = "NT1 - SIGNING_REQUIRED",
11257 : .signing_setting = SMB_SIGNING_REQUIRED,
11258 : .protocol = PROTOCOL_NT1,
11259 : },
11260 : };
11261 :
11262 5 : printf("starting large_readx test\n");
11263 :
11264 5 : if (!torture_open_connection(&cli1, 0)) {
11265 0 : goto out;
11266 : }
11267 :
11268 5 : normal_caps = smb1cli_conn_capabilities(cli1->conn);
11269 :
11270 5 : if (!(normal_caps & CAP_LARGE_READX)) {
11271 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11272 : (unsigned int)normal_caps);
11273 0 : goto out;
11274 : }
11275 :
11276 : /* Create a file of size 4MB. */
11277 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11278 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11279 : 0, 0, &fnum1, NULL);
11280 :
11281 5 : if (!NT_STATUS_IS_OK(status)) {
11282 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11283 0 : goto out;
11284 : }
11285 :
11286 : /* Write file_size bytes. */
11287 5 : buf = talloc_zero_array(frame, uint8_t, file_size);
11288 5 : if (buf == NULL) {
11289 0 : goto out;
11290 : }
11291 :
11292 5 : status = cli_writeall(cli1,
11293 : fnum1,
11294 : 0,
11295 : buf,
11296 : 0,
11297 : file_size,
11298 : NULL);
11299 5 : if (!NT_STATUS_IS_OK(status)) {
11300 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11301 0 : goto out;
11302 : }
11303 :
11304 5 : status = cli_close(cli1, fnum1);
11305 5 : if (!NT_STATUS_IS_OK(status)) {
11306 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11307 0 : goto out;
11308 : }
11309 :
11310 5 : fnum1 = UINT16_MAX;
11311 :
11312 15 : for (i=0; i < ARRAY_SIZE(runs); i++) {
11313 10 : enum smb_signing_setting saved_signing_setting = signing_state;
11314 10 : uint16_t fnum2 = -1;
11315 :
11316 14 : if (do_encrypt &&
11317 4 : (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11318 : {
11319 2 : d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11320 2 : continue;
11321 : }
11322 :
11323 8 : d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11324 :
11325 8 : signing_state = runs[i].signing_setting;
11326 8 : cli2 = open_nbt_connection();
11327 8 : signing_state = saved_signing_setting;
11328 8 : if (cli2 == NULL) {
11329 0 : goto out;
11330 : }
11331 :
11332 16 : status = smbXcli_negprot(cli2->conn,
11333 8 : cli2->timeout,
11334 : runs[i].protocol,
11335 : runs[i].protocol);
11336 8 : if (!NT_STATUS_IS_OK(status)) {
11337 0 : goto out;
11338 : }
11339 :
11340 8 : status = cli_session_setup_creds(cli2, torture_creds);
11341 8 : if (!NT_STATUS_IS_OK(status)) {
11342 0 : goto out;
11343 : }
11344 :
11345 8 : status = cli_tree_connect(cli2,
11346 : share,
11347 : "?????",
11348 : password);
11349 8 : if (!NT_STATUS_IS_OK(status)) {
11350 0 : goto out;
11351 : }
11352 :
11353 8 : cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11354 :
11355 8 : normal_caps = smb1cli_conn_capabilities(cli2->conn);
11356 :
11357 8 : if (!(normal_caps & CAP_LARGE_READX)) {
11358 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11359 : (unsigned int)normal_caps);
11360 0 : goto out;
11361 : }
11362 :
11363 8 : if (do_encrypt) {
11364 2 : if (force_cli_encryption(cli2, share) == false) {
11365 0 : goto out;
11366 : }
11367 6 : } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11368 : uint16_t major, minor;
11369 : uint32_t caplow, caphigh;
11370 :
11371 4 : status = cli_unix_extensions_version(cli2,
11372 : &major, &minor,
11373 : &caplow, &caphigh);
11374 4 : if (!NT_STATUS_IS_OK(status)) {
11375 0 : goto out;
11376 : }
11377 : }
11378 :
11379 8 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11380 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11381 : 0, 0, &fnum2, NULL);
11382 8 : if (!NT_STATUS_IS_OK(status)) {
11383 0 : d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11384 0 : goto out;
11385 : }
11386 :
11387 : /* All reads must return less than file_size bytes. */
11388 8 : if (!large_readx_tests(cli2, fnum2, buf)) {
11389 0 : goto out;
11390 : }
11391 :
11392 8 : status = cli_close(cli2, fnum2);
11393 8 : if (!NT_STATUS_IS_OK(status)) {
11394 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11395 0 : goto out;
11396 : }
11397 8 : fnum2 = -1;
11398 :
11399 8 : if (!torture_close_connection(cli2)) {
11400 0 : goto out;
11401 : }
11402 8 : cli2 = NULL;
11403 : }
11404 :
11405 5 : correct = true;
11406 5 : printf("Success on large_readx test\n");
11407 :
11408 5 : out:
11409 :
11410 5 : if (cli2) {
11411 0 : if (!torture_close_connection(cli2)) {
11412 0 : correct = false;
11413 : }
11414 : }
11415 :
11416 5 : if (cli1) {
11417 5 : if (fnum1 != UINT16_MAX) {
11418 0 : status = cli_close(cli1, fnum1);
11419 0 : if (!NT_STATUS_IS_OK(status)) {
11420 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11421 : }
11422 0 : fnum1 = UINT16_MAX;
11423 : }
11424 :
11425 5 : status = cli_unlink(cli1, fname,
11426 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11427 5 : if (!NT_STATUS_IS_OK(status)) {
11428 0 : printf("unlink failed (%s)\n", nt_errstr(status));
11429 : }
11430 :
11431 5 : if (!torture_close_connection(cli1)) {
11432 0 : correct = false;
11433 : }
11434 : }
11435 :
11436 5 : TALLOC_FREE(frame);
11437 :
11438 5 : printf("finished large_readx test\n");
11439 5 : return correct;
11440 : }
11441 :
11442 20 : static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11443 : const char *mask,
11444 : void *private_data)
11445 : {
11446 20 : uint32_t *p_attr = (uint32_t *)private_data;
11447 :
11448 20 : if (strequal(finfo->name, test_filename)) {
11449 4 : *p_attr = finfo->attr;
11450 : }
11451 :
11452 20 : return NT_STATUS_OK;
11453 : }
11454 :
11455 4 : static bool run_msdfs_attribute(int dummy)
11456 : {
11457 : static struct cli_state *cli;
11458 4 : bool correct = false;
11459 4 : uint32_t attr = 0;
11460 : NTSTATUS status;
11461 :
11462 4 : printf("Starting MSDFS-ATTRIBUTE test\n");
11463 :
11464 4 : if (test_filename == NULL || test_filename[0] == '\0') {
11465 0 : printf("MSDFS-ATTRIBUTE test "
11466 : "needs -f filename-of-msdfs-link\n");
11467 0 : return false;
11468 : }
11469 :
11470 : /*
11471 : * NB. We use torture_open_connection_flags() not
11472 : * torture_open_connection() as the latter forces
11473 : * SMB1.
11474 : */
11475 4 : if (!torture_open_connection_flags(&cli, 0, 0)) {
11476 0 : return false;
11477 : }
11478 :
11479 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11480 :
11481 4 : status = cli_list(cli,
11482 : "*",
11483 : FILE_ATTRIBUTE_DIRECTORY,
11484 : msdfs_attribute_list_fn,
11485 : &attr);
11486 :
11487 4 : if (!NT_STATUS_IS_OK(status)) {
11488 0 : printf("cli_list failed with %s\n",
11489 : nt_errstr(status));
11490 0 : goto out;
11491 : }
11492 4 : if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11493 0 : printf("file %s should have "
11494 : "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11495 : test_filename,
11496 : (unsigned int)attr);
11497 0 : goto out;
11498 : }
11499 :
11500 4 : if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11501 0 : printf("file %s should have "
11502 : "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11503 : test_filename,
11504 : (unsigned int)attr);
11505 0 : goto out;
11506 : }
11507 :
11508 4 : correct = true;
11509 :
11510 4 : out:
11511 :
11512 4 : torture_close_connection(cli);
11513 4 : return correct;
11514 : }
11515 :
11516 0 : static bool run_cli_echo(int dummy)
11517 : {
11518 : struct cli_state *cli;
11519 : NTSTATUS status;
11520 :
11521 0 : printf("starting cli_echo test\n");
11522 0 : if (!torture_open_connection(&cli, 0)) {
11523 0 : return false;
11524 : }
11525 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11526 :
11527 0 : status = cli_echo(cli, 5, data_blob_const("hello", 5));
11528 :
11529 0 : d_printf("cli_echo returned %s\n", nt_errstr(status));
11530 :
11531 0 : torture_close_connection(cli);
11532 0 : return NT_STATUS_IS_OK(status);
11533 : }
11534 :
11535 14 : static int splice_status(off_t written, void *priv)
11536 : {
11537 14 : return true;
11538 : }
11539 :
11540 7 : static bool run_cli_splice(int dummy)
11541 : {
11542 7 : uint8_t *buf = NULL;
11543 7 : struct cli_state *cli1 = NULL;
11544 7 : bool correct = false;
11545 7 : const char *fname_src = "\\splice_src.dat";
11546 7 : const char *fname_dst = "\\splice_dst.dat";
11547 : NTSTATUS status;
11548 7 : uint16_t fnum1 = UINT16_MAX;
11549 7 : uint16_t fnum2 = UINT16_MAX;
11550 7 : size_t file_size = 2*1024*1024;
11551 7 : size_t splice_size = 1*1024*1024 + 713;
11552 : uint8_t digest1[16], digest2[16];
11553 7 : off_t written = 0;
11554 7 : size_t nread = 0;
11555 7 : TALLOC_CTX *frame = talloc_stackframe();
11556 :
11557 7 : printf("starting cli_splice test\n");
11558 :
11559 7 : if (!torture_open_connection(&cli1, 0)) {
11560 0 : goto out;
11561 : }
11562 :
11563 7 : cli_unlink(cli1, fname_src,
11564 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11565 7 : cli_unlink(cli1, fname_dst,
11566 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11567 :
11568 : /* Create a file */
11569 7 : status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11570 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11571 : 0, 0, &fnum1, NULL);
11572 :
11573 7 : if (!NT_STATUS_IS_OK(status)) {
11574 0 : d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11575 0 : goto out;
11576 : }
11577 :
11578 : /* Write file_size bytes - must be bigger than splice_size. */
11579 7 : buf = talloc_zero_array(frame, uint8_t, file_size);
11580 7 : if (buf == NULL) {
11581 0 : d_printf("talloc_fail\n");
11582 0 : goto out;
11583 : }
11584 :
11585 : /* Fill it with random numbers. */
11586 7 : generate_random_buffer(buf, file_size);
11587 :
11588 : /* MD5 the first 1MB + 713 bytes. */
11589 7 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11590 : buf,
11591 : splice_size,
11592 : digest1);
11593 :
11594 7 : status = cli_writeall(cli1,
11595 : fnum1,
11596 : 0,
11597 : buf,
11598 : 0,
11599 : file_size,
11600 : NULL);
11601 7 : if (!NT_STATUS_IS_OK(status)) {
11602 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11603 0 : goto out;
11604 : }
11605 :
11606 7 : status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11607 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11608 : 0, 0, &fnum2, NULL);
11609 :
11610 7 : if (!NT_STATUS_IS_OK(status)) {
11611 0 : d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11612 0 : goto out;
11613 : }
11614 :
11615 : /* Now splice 1MB + 713 bytes. */
11616 7 : status = cli_splice(cli1,
11617 : cli1,
11618 : fnum1,
11619 : fnum2,
11620 : splice_size,
11621 : 0,
11622 : 0,
11623 : &written,
11624 : splice_status,
11625 : NULL);
11626 :
11627 7 : if (!NT_STATUS_IS_OK(status)) {
11628 0 : d_printf("cli_splice failed: %s\n", nt_errstr(status));
11629 0 : goto out;
11630 : }
11631 :
11632 : /* Clear the old buffer. */
11633 7 : memset(buf, '\0', file_size);
11634 :
11635 : /* Read the new file. */
11636 7 : status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11637 7 : if (!NT_STATUS_IS_OK(status)) {
11638 0 : d_printf("cli_read failed: %s\n", nt_errstr(status));
11639 0 : goto out;
11640 : }
11641 7 : if (nread != splice_size) {
11642 0 : d_printf("bad read of 0x%x, should be 0x%x\n",
11643 : (unsigned int)nread,
11644 : (unsigned int)splice_size);
11645 0 : goto out;
11646 : }
11647 :
11648 : /* MD5 the first 1MB + 713 bytes. */
11649 7 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11650 : buf,
11651 : splice_size,
11652 : digest2);
11653 :
11654 : /* Must be the same. */
11655 7 : if (memcmp(digest1, digest2, 16) != 0) {
11656 0 : d_printf("bad MD5 compare\n");
11657 0 : goto out;
11658 : }
11659 :
11660 7 : correct = true;
11661 7 : printf("Success on cli_splice test\n");
11662 :
11663 7 : out:
11664 :
11665 7 : if (cli1) {
11666 7 : if (fnum1 != UINT16_MAX) {
11667 7 : cli_close(cli1, fnum1);
11668 : }
11669 7 : if (fnum2 != UINT16_MAX) {
11670 7 : cli_close(cli1, fnum2);
11671 : }
11672 :
11673 7 : cli_unlink(cli1, fname_src,
11674 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11675 7 : cli_unlink(cli1, fname_dst,
11676 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11677 :
11678 7 : if (!torture_close_connection(cli1)) {
11679 0 : correct = false;
11680 : }
11681 : }
11682 :
11683 7 : TALLOC_FREE(frame);
11684 7 : return correct;
11685 : }
11686 :
11687 4 : static bool run_uid_regression_test(int dummy)
11688 : {
11689 : static struct cli_state *cli;
11690 : int16_t old_vuid;
11691 : int32_t old_cnum;
11692 4 : bool correct = True;
11693 4 : struct smbXcli_tcon *tcon_copy = NULL;
11694 : NTSTATUS status;
11695 :
11696 4 : printf("starting uid regression test\n");
11697 :
11698 4 : if (!torture_open_connection(&cli, 0)) {
11699 0 : return False;
11700 : }
11701 :
11702 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11703 :
11704 : /* Ok - now save then logoff our current user. */
11705 4 : old_vuid = cli_state_get_uid(cli);
11706 :
11707 4 : status = cli_ulogoff(cli);
11708 4 : if (!NT_STATUS_IS_OK(status)) {
11709 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
11710 : __location__, nt_errstr(status));
11711 0 : correct = false;
11712 0 : goto out;
11713 : }
11714 :
11715 4 : cli_state_set_uid(cli, old_vuid);
11716 :
11717 : /* Try an operation. */
11718 4 : status = cli_mkdir(cli, "\\uid_reg_test");
11719 4 : if (NT_STATUS_IS_OK(status)) {
11720 0 : d_printf("(%s) cli_mkdir succeeded\n",
11721 : __location__);
11722 0 : correct = false;
11723 0 : goto out;
11724 : } else {
11725 : /* Should be bad uid. */
11726 4 : if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11727 4 : NT_STATUS_USER_SESSION_DELETED)) {
11728 0 : correct = false;
11729 0 : goto out;
11730 : }
11731 : }
11732 :
11733 4 : old_cnum = cli_state_get_tid(cli);
11734 : /*
11735 : * This is an SMB1-only test.
11736 : * Copy the tcon, not "save/restore".
11737 : *
11738 : * In SMB1 the cli_tdis() below frees
11739 : * cli->smb1.tcon so we need a copy
11740 : * of the struct to put back for the
11741 : * second tdis call with invalid vuid.
11742 : *
11743 : * This is a test-only hack. Real client code
11744 : * uses cli_state_save_tcon()/cli_state_restore_tcon().
11745 : */
11746 4 : tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11747 4 : if (tcon_copy == NULL) {
11748 0 : correct = false;
11749 0 : goto out;
11750 : }
11751 :
11752 : /* Now try a SMBtdis with the invalid vuid set to zero. */
11753 4 : cli_state_set_uid(cli, 0);
11754 :
11755 : /* This should succeed. */
11756 4 : status = cli_tdis(cli);
11757 :
11758 4 : if (NT_STATUS_IS_OK(status)) {
11759 4 : d_printf("First tdis with invalid vuid should succeed.\n");
11760 : } else {
11761 0 : d_printf("First tdis failed (%s)\n", nt_errstr(status));
11762 0 : correct = false;
11763 0 : cli->smb1.tcon = tcon_copy;
11764 0 : goto out;
11765 : }
11766 :
11767 4 : cli->smb1.tcon = tcon_copy;
11768 4 : cli_state_set_uid(cli, old_vuid);
11769 4 : cli_state_set_tid(cli, old_cnum);
11770 :
11771 : /* This should fail. */
11772 4 : status = cli_tdis(cli);
11773 4 : if (NT_STATUS_IS_OK(status)) {
11774 0 : d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11775 0 : correct = false;
11776 0 : goto out;
11777 : } else {
11778 : /* Should be bad tid. */
11779 4 : if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11780 4 : NT_STATUS_NETWORK_NAME_DELETED)) {
11781 0 : correct = false;
11782 0 : goto out;
11783 : }
11784 : }
11785 :
11786 4 : cli_rmdir(cli, "\\uid_reg_test");
11787 :
11788 4 : out:
11789 :
11790 4 : cli_shutdown(cli);
11791 4 : return correct;
11792 : }
11793 :
11794 :
11795 : static const char *illegal_chars = "*\\/?<>|\":";
11796 : static char force_shortname_chars[] = " +,.[];=\177";
11797 :
11798 8 : static NTSTATUS shortname_del_fn(struct file_info *finfo,
11799 : const char *mask, void *state)
11800 : {
11801 8 : struct cli_state *pcli = (struct cli_state *)state;
11802 : fstring fname;
11803 8 : NTSTATUS status = NT_STATUS_OK;
11804 :
11805 8 : slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11806 :
11807 8 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11808 8 : return NT_STATUS_OK;
11809 :
11810 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11811 0 : status = cli_rmdir(pcli, fname);
11812 0 : if (!NT_STATUS_IS_OK(status)) {
11813 0 : printf("del_fn: failed to rmdir %s\n,", fname );
11814 : }
11815 : } else {
11816 0 : status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11817 0 : if (!NT_STATUS_IS_OK(status)) {
11818 0 : printf("del_fn: failed to unlink %s\n,", fname );
11819 : }
11820 : }
11821 0 : return status;
11822 : }
11823 :
11824 : struct sn_state {
11825 : int matched;
11826 : int i;
11827 : bool val;
11828 : };
11829 :
11830 348 : static NTSTATUS shortname_list_fn(struct file_info *finfo,
11831 : const char *name, void *state)
11832 : {
11833 348 : struct sn_state *s = (struct sn_state *)state;
11834 348 : int i = s->i;
11835 :
11836 : #if 0
11837 : printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11838 : i, finfo->name, finfo->short_name);
11839 : #endif
11840 :
11841 348 : if (strchr(force_shortname_chars, i)) {
11842 36 : if (!finfo->short_name) {
11843 : /* Shortname not created when it should be. */
11844 0 : d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11845 : __location__, finfo->name, i);
11846 0 : s->val = true;
11847 : }
11848 312 : } else if (finfo->short_name){
11849 : /* Shortname created when it should not be. */
11850 0 : d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11851 : __location__, finfo->short_name, finfo->name);
11852 0 : s->val = true;
11853 : }
11854 348 : s->matched += 1;
11855 348 : return NT_STATUS_OK;
11856 : }
11857 :
11858 4 : static bool run_shortname_test(int dummy)
11859 : {
11860 : static struct cli_state *cli;
11861 4 : bool correct = True;
11862 : int i;
11863 : struct sn_state s;
11864 : char fname[40];
11865 : NTSTATUS status;
11866 :
11867 4 : printf("starting shortname test\n");
11868 :
11869 4 : if (!torture_open_connection(&cli, 0)) {
11870 0 : return False;
11871 : }
11872 :
11873 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11874 :
11875 4 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11876 4 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11877 4 : cli_rmdir(cli, "\\shortname");
11878 :
11879 4 : status = cli_mkdir(cli, "\\shortname");
11880 4 : if (!NT_STATUS_IS_OK(status)) {
11881 0 : d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11882 : __location__, nt_errstr(status));
11883 0 : correct = false;
11884 0 : goto out;
11885 : }
11886 :
11887 4 : if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11888 0 : correct = false;
11889 0 : goto out;
11890 : }
11891 4 : if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11892 0 : correct = false;
11893 0 : goto out;
11894 : }
11895 :
11896 4 : s.val = false;
11897 :
11898 388 : for (i = 32; i < 128; i++) {
11899 384 : uint16_t fnum = (uint16_t)-1;
11900 :
11901 384 : s.i = i;
11902 :
11903 384 : if (strchr(illegal_chars, i)) {
11904 36 : continue;
11905 : }
11906 348 : fname[15] = i;
11907 :
11908 348 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
11909 : FILE_SHARE_READ|FILE_SHARE_WRITE,
11910 : FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
11911 348 : if (!NT_STATUS_IS_OK(status)) {
11912 0 : d_printf("(%s) cli_nt_create of %s failed: %s\n",
11913 : __location__, fname, nt_errstr(status));
11914 0 : correct = false;
11915 0 : goto out;
11916 : }
11917 348 : cli_close(cli, fnum);
11918 :
11919 348 : s.matched = 0;
11920 348 : status = cli_list(cli, "\\shortname\\test*.*", 0,
11921 : shortname_list_fn, &s);
11922 348 : if (s.matched != 1) {
11923 0 : d_printf("(%s) failed to list %s: %s\n",
11924 : __location__, fname, nt_errstr(status));
11925 0 : correct = false;
11926 0 : goto out;
11927 : }
11928 :
11929 348 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11930 348 : if (!NT_STATUS_IS_OK(status)) {
11931 0 : d_printf("(%s) failed to delete %s: %s\n",
11932 : __location__, fname, nt_errstr(status));
11933 0 : correct = false;
11934 0 : goto out;
11935 : }
11936 :
11937 348 : if (s.val) {
11938 0 : correct = false;
11939 0 : goto out;
11940 : }
11941 : }
11942 :
11943 4 : out:
11944 :
11945 4 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11946 4 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11947 4 : cli_rmdir(cli, "\\shortname");
11948 4 : torture_close_connection(cli);
11949 4 : return correct;
11950 : }
11951 :
11952 : TLDAPRC callback_code;
11953 :
11954 448 : static void pagedsearch_cb(struct tevent_req *req)
11955 : {
11956 : TLDAPRC rc;
11957 : struct tldap_message *msg;
11958 : char *dn;
11959 :
11960 448 : rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
11961 448 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
11962 0 : d_printf("tldap_search_paged_recv failed: %s\n",
11963 : tldap_rc2string(rc));
11964 0 : callback_code = rc;
11965 4 : return;
11966 : }
11967 448 : if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
11968 8 : TALLOC_FREE(msg);
11969 8 : return;
11970 : }
11971 440 : if (!tldap_entry_dn(msg, &dn)) {
11972 0 : d_printf("tldap_entry_dn failed\n");
11973 0 : return;
11974 : }
11975 440 : d_printf("%s\n", dn);
11976 440 : TALLOC_FREE(msg);
11977 : }
11978 :
11979 : enum tldap_extended_val {
11980 : EXTENDED_ZERO = 0,
11981 : EXTENDED_ONE = 1,
11982 : EXTENDED_NONE = 2,
11983 : };
11984 :
11985 : /*
11986 : * Construct an extended dn control with either no value, 0 or 1
11987 : *
11988 : * No value and 0 are equivalent (non-hyphenated GUID)
11989 : * 1 has the hyphenated GUID
11990 : */
11991 : static struct tldap_control *
11992 6 : tldap_build_extended_control(enum tldap_extended_val val)
11993 : {
11994 : struct tldap_control empty_control;
11995 : struct asn1_data *data;
11996 :
11997 6 : ZERO_STRUCT(empty_control);
11998 :
11999 6 : if (val != EXTENDED_NONE) {
12000 4 : data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12001 :
12002 4 : if (!data) {
12003 0 : return NULL;
12004 : }
12005 :
12006 4 : if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12007 0 : return NULL;
12008 : }
12009 :
12010 4 : if (!asn1_write_Integer(data, (int)val)) {
12011 0 : return NULL;
12012 : }
12013 :
12014 4 : if (!asn1_pop_tag(data)) {
12015 0 : return NULL;
12016 : }
12017 :
12018 4 : if (!asn1_blob(data, &empty_control.value)) {
12019 0 : return NULL;
12020 : }
12021 : }
12022 :
12023 6 : empty_control.oid = "1.2.840.113556.1.4.529";
12024 6 : empty_control.critical = true;
12025 :
12026 6 : return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12027 :
12028 : }
12029 :
12030 6 : static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12031 : enum tldap_extended_val control_val)
12032 : {
12033 6 : struct tldap_control *control = tldap_build_extended_control(control_val);
12034 6 : char *dn = NULL;
12035 : struct tldap_message **msg;
12036 : TLDAPRC rc;
12037 :
12038 6 : rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12039 : "(objectClass=*)", NULL, 0, 0,
12040 : control, 1, NULL,
12041 : 0, 0, 0, 0, talloc_tos(), &msg);
12042 6 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12043 0 : d_printf("tldap_search for domain DN failed: %s\n",
12044 : tldap_errstr(talloc_tos(), ld, rc));
12045 0 : return false;
12046 : }
12047 :
12048 6 : if (!tldap_entry_dn(msg[0], &dn)) {
12049 0 : d_printf("tldap_search domain DN fetch failed: %s\n",
12050 : tldap_errstr(talloc_tos(), ld, rc));
12051 0 : return false;
12052 : }
12053 :
12054 6 : d_printf("%s\n", dn);
12055 : {
12056 : uint32_t time_low;
12057 : uint32_t time_mid, time_hi_and_version;
12058 : uint32_t clock_seq[2];
12059 : uint32_t node[6];
12060 : char next;
12061 :
12062 6 : switch (control_val) {
12063 4 : case EXTENDED_NONE:
12064 : case EXTENDED_ZERO:
12065 : /*
12066 : * When reading GUIDs with hyphens, scanf will treat
12067 : * hyphen as a hex character (and counts as part of the
12068 : * width). This creates leftover GUID string which we
12069 : * check will for with 'next' and closing '>'.
12070 : */
12071 4 : if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12072 : &time_low, &time_mid,
12073 : &time_hi_and_version, &clock_seq[0],
12074 : &clock_seq[1], &node[0], &node[1],
12075 : &node[2], &node[3], &node[4],
12076 : &node[5], &next)) {
12077 : /* This GUID is good */
12078 : } else {
12079 0 : d_printf("GUID format in control (no hyphens) doesn't match output\n");
12080 0 : return false;
12081 : }
12082 :
12083 4 : break;
12084 2 : case EXTENDED_ONE:
12085 2 : if (12 == sscanf(dn,
12086 : "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12087 : &time_low, &time_mid,
12088 : &time_hi_and_version, &clock_seq[0],
12089 : &clock_seq[1], &node[0], &node[1],
12090 : &node[2], &node[3], &node[4],
12091 : &node[5], &next)) {
12092 : /* This GUID is good */
12093 : } else {
12094 0 : d_printf("GUID format in control (with hyphens) doesn't match output\n");
12095 0 : return false;
12096 : }
12097 :
12098 2 : break;
12099 0 : default:
12100 0 : return false;
12101 : }
12102 : }
12103 :
12104 6 : return true;
12105 : }
12106 :
12107 2 : static bool run_tldap(int dummy)
12108 : {
12109 : struct tldap_context *ld;
12110 : int fd;
12111 : TLDAPRC rc;
12112 : NTSTATUS status;
12113 : struct sockaddr_storage addr;
12114 : struct tevent_context *ev;
12115 : struct tevent_req *req;
12116 : char *basedn;
12117 : const char *filter;
12118 :
12119 2 : if (!resolve_name(host, &addr, 0, false)) {
12120 0 : d_printf("could not find host %s\n", host);
12121 0 : return false;
12122 : }
12123 2 : status = open_socket_out(&addr, 389, 9999, &fd);
12124 2 : if (!NT_STATUS_IS_OK(status)) {
12125 0 : d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12126 0 : return false;
12127 : }
12128 :
12129 2 : ld = tldap_context_create(talloc_tos(), fd);
12130 2 : if (ld == NULL) {
12131 0 : close(fd);
12132 0 : d_printf("tldap_context_create failed\n");
12133 0 : return false;
12134 : }
12135 :
12136 2 : rc = tldap_fetch_rootdse(ld);
12137 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12138 0 : d_printf("tldap_fetch_rootdse failed: %s\n",
12139 : tldap_errstr(talloc_tos(), ld, rc));
12140 0 : return false;
12141 : }
12142 :
12143 2 : basedn = tldap_talloc_single_attribute(
12144 : tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12145 2 : if (basedn == NULL) {
12146 0 : d_printf("no defaultNamingContext\n");
12147 0 : return false;
12148 : }
12149 2 : d_printf("defaultNamingContext: %s\n", basedn);
12150 :
12151 2 : ev = samba_tevent_context_init(talloc_tos());
12152 2 : if (ev == NULL) {
12153 0 : d_printf("tevent_context_init failed\n");
12154 0 : return false;
12155 : }
12156 :
12157 2 : rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12158 : loadparm_init_s3(talloc_tos(),
12159 : loadparm_s3_helpers()),
12160 : GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12161 :
12162 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12163 0 : d_printf("tldap_gensec_bind failed\n");
12164 0 : return false;
12165 : }
12166 :
12167 2 : callback_code = TLDAP_SUCCESS;
12168 :
12169 2 : req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12170 : TLDAP_SCOPE_SUB, "(objectclass=*)",
12171 : NULL, 0, 0,
12172 : NULL, 0, NULL, 0, 0, 0, 0, 5);
12173 2 : if (req == NULL) {
12174 0 : d_printf("tldap_search_paged_send failed\n");
12175 0 : return false;
12176 : }
12177 2 : tevent_req_set_callback(req, pagedsearch_cb, NULL);
12178 :
12179 2 : tevent_req_poll(req, ev);
12180 :
12181 2 : TALLOC_FREE(req);
12182 :
12183 2 : rc = callback_code;
12184 :
12185 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12186 0 : d_printf("tldap_search with paging failed: %s\n",
12187 : tldap_errstr(talloc_tos(), ld, rc));
12188 0 : return false;
12189 : }
12190 :
12191 : /* test search filters against rootDSE */
12192 2 : filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12193 : "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12194 :
12195 2 : rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12196 : NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12197 : talloc_tos(), NULL);
12198 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12199 0 : d_printf("tldap_search with complex filter failed: %s\n",
12200 : tldap_errstr(talloc_tos(), ld, rc));
12201 0 : return false;
12202 : }
12203 :
12204 : /*
12205 : * Tests to check for regression of:
12206 : *
12207 : * https://bugzilla.samba.org/show_bug.cgi?id=14029
12208 : *
12209 : * TLDAP used here to pick apart the original string DN (with GUID)
12210 : */
12211 2 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12212 0 : d_printf("tldap_search with extended dn (no val) failed: %s\n",
12213 : tldap_errstr(talloc_tos(), ld, rc));
12214 0 : return false;
12215 : }
12216 2 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12217 0 : d_printf("tldap_search with extended dn (0) failed: %s\n",
12218 : tldap_errstr(talloc_tos(), ld, rc));
12219 0 : return false;
12220 : }
12221 2 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12222 0 : d_printf("tldap_search with extended dn (1) failed: %s\n",
12223 : tldap_errstr(talloc_tos(), ld, rc));
12224 0 : return false;
12225 : }
12226 :
12227 2 : TALLOC_FREE(ld);
12228 2 : return true;
12229 : }
12230 :
12231 : /* Torture test to ensure no regression of :
12232 : https://bugzilla.samba.org/show_bug.cgi?id=7084
12233 : */
12234 :
12235 4 : static bool run_dir_createtime(int dummy)
12236 : {
12237 : struct cli_state *cli;
12238 4 : const char *dname = "\\testdir_createtime";
12239 4 : const char *fname = "\\testdir_createtime\\testfile";
12240 : NTSTATUS status;
12241 : struct timespec create_time;
12242 : struct timespec create_time1;
12243 : uint16_t fnum;
12244 4 : bool ret = false;
12245 : uint64_t ino;
12246 :
12247 4 : if (!torture_open_connection(&cli, 0)) {
12248 0 : return false;
12249 : }
12250 :
12251 4 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12252 : /* Ensure ino is zero, SMB2 gets a real one. */
12253 0 : ino = 0;
12254 : } else {
12255 : /* Ensure ino is -1, SMB1 never gets a real one. */
12256 4 : ino = (uint64_t)-1;
12257 : }
12258 :
12259 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12260 4 : cli_rmdir(cli, dname);
12261 :
12262 4 : status = cli_mkdir(cli, dname);
12263 4 : if (!NT_STATUS_IS_OK(status)) {
12264 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12265 0 : goto out;
12266 : }
12267 :
12268 4 : status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12269 : NULL, NULL, &ino);
12270 4 : if (!NT_STATUS_IS_OK(status)) {
12271 0 : printf("cli_qpathinfo2 returned %s\n",
12272 : nt_errstr(status));
12273 0 : goto out;
12274 : }
12275 :
12276 4 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12277 : /* SMB2 should always return an inode. */
12278 0 : if (ino == 0) {
12279 0 : printf("SMB2 bad inode (0)\n");
12280 0 : goto out;
12281 : }
12282 : } else {
12283 : /* SMB1 must always return zero here. */
12284 4 : if (ino != 0) {
12285 0 : printf("SMB1 bad inode (!0)\n");
12286 0 : goto out;
12287 : }
12288 : }
12289 :
12290 : /* Sleep 3 seconds, then create a file. */
12291 4 : sleep(3);
12292 :
12293 4 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12294 : DENY_NONE, &fnum);
12295 4 : if (!NT_STATUS_IS_OK(status)) {
12296 0 : printf("cli_openx failed: %s\n", nt_errstr(status));
12297 0 : goto out;
12298 : }
12299 :
12300 4 : status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12301 : NULL, NULL, NULL);
12302 4 : if (!NT_STATUS_IS_OK(status)) {
12303 0 : printf("cli_qpathinfo2 (2) returned %s\n",
12304 : nt_errstr(status));
12305 0 : goto out;
12306 : }
12307 :
12308 4 : if (timespec_compare(&create_time1, &create_time)) {
12309 0 : printf("run_dir_createtime: create time was updated (error)\n");
12310 : } else {
12311 4 : printf("run_dir_createtime: create time was not updated (correct)\n");
12312 4 : ret = true;
12313 : }
12314 :
12315 4 : out:
12316 :
12317 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12318 4 : cli_rmdir(cli, dname);
12319 4 : if (!torture_close_connection(cli)) {
12320 0 : ret = false;
12321 : }
12322 4 : return ret;
12323 : }
12324 :
12325 :
12326 4 : static bool run_streamerror(int dummy)
12327 : {
12328 : struct cli_state *cli;
12329 4 : const char *dname = "\\testdir_streamerror";
12330 4 : const char *streamname =
12331 : "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12332 : NTSTATUS status;
12333 : time_t change_time, access_time, write_time;
12334 : off_t size;
12335 : uint16_t fnum;
12336 : uint32_t attr;
12337 4 : bool ret = true;
12338 :
12339 4 : if (!torture_open_connection(&cli, 0)) {
12340 0 : return false;
12341 : }
12342 :
12343 4 : cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12344 4 : cli_rmdir(cli, dname);
12345 :
12346 4 : status = cli_mkdir(cli, dname);
12347 4 : if (!NT_STATUS_IS_OK(status)) {
12348 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12349 0 : return false;
12350 : }
12351 :
12352 4 : status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12353 : &write_time, &size, &attr);
12354 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12355 0 : printf("pathinfo returned %s, expected "
12356 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12357 : nt_errstr(status));
12358 0 : ret = false;
12359 : }
12360 :
12361 4 : status = cli_ntcreate(cli, streamname, 0x16,
12362 : FILE_READ_DATA|FILE_READ_EA|
12363 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12364 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12365 : FILE_OPEN, 0, 0, &fnum, NULL);
12366 :
12367 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12368 0 : printf("ntcreate returned %s, expected "
12369 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12370 : nt_errstr(status));
12371 0 : ret = false;
12372 : }
12373 :
12374 :
12375 4 : cli_rmdir(cli, dname);
12376 4 : return ret;
12377 : }
12378 :
12379 : struct pidtest_state {
12380 : bool success;
12381 : uint16_t vwv[1];
12382 : DATA_BLOB data;
12383 : };
12384 :
12385 : static void pid_echo_done(struct tevent_req *subreq);
12386 :
12387 4 : static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12388 : struct tevent_context *ev,
12389 : struct cli_state *cli)
12390 : {
12391 : struct tevent_req *req, *subreq;
12392 : struct pidtest_state *state;
12393 :
12394 4 : req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12395 4 : if (req == NULL) {
12396 0 : return NULL;
12397 : }
12398 :
12399 4 : SSVAL(state->vwv, 0, 1);
12400 4 : state->data = data_blob_const("hello", 5);
12401 :
12402 8 : subreq = smb1cli_req_send(state,
12403 : ev,
12404 : cli->conn,
12405 : SMBecho,
12406 : 0, 0, /* *_flags */
12407 : 0, 0, /* *_flags2 */
12408 4 : cli->timeout,
12409 : 0xDEADBEEF, /* pid */
12410 : NULL, /* tcon */
12411 : NULL, /* session */
12412 4 : ARRAY_SIZE(state->vwv), state->vwv,
12413 4 : state->data.length, state->data.data);
12414 :
12415 4 : if (tevent_req_nomem(subreq, req)) {
12416 0 : return tevent_req_post(req, ev);
12417 : }
12418 4 : tevent_req_set_callback(subreq, pid_echo_done, req);
12419 4 : return req;
12420 : }
12421 :
12422 4 : static void pid_echo_done(struct tevent_req *subreq)
12423 : {
12424 4 : struct tevent_req *req = tevent_req_callback_data(
12425 : subreq, struct tevent_req);
12426 4 : struct pidtest_state *state = tevent_req_data(
12427 : req, struct pidtest_state);
12428 : NTSTATUS status;
12429 : uint32_t num_bytes;
12430 4 : uint8_t *bytes = NULL;
12431 4 : struct iovec *recv_iov = NULL;
12432 4 : uint8_t *phdr = NULL;
12433 4 : uint16_t pidlow = 0;
12434 4 : uint16_t pidhigh = 0;
12435 4 : struct smb1cli_req_expected_response expected[] = {
12436 : {
12437 : .status = NT_STATUS_OK,
12438 : .wct = 1,
12439 : },
12440 : };
12441 :
12442 4 : status = smb1cli_req_recv(subreq, state,
12443 : &recv_iov,
12444 : &phdr,
12445 : NULL, /* pwct */
12446 : NULL, /* pvwv */
12447 : NULL, /* pvwv_offset */
12448 : &num_bytes,
12449 : &bytes,
12450 : NULL, /* pbytes_offset */
12451 : NULL, /* pinbuf */
12452 : expected, ARRAY_SIZE(expected));
12453 :
12454 4 : TALLOC_FREE(subreq);
12455 :
12456 4 : if (!NT_STATUS_IS_OK(status)) {
12457 0 : tevent_req_nterror(req, status);
12458 0 : return;
12459 : }
12460 :
12461 4 : if (num_bytes != state->data.length) {
12462 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12463 0 : return;
12464 : }
12465 :
12466 4 : if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12467 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12468 0 : return;
12469 : }
12470 :
12471 : /* Check pid low/high == DEADBEEF */
12472 4 : pidlow = SVAL(phdr, HDR_PID);
12473 4 : if (pidlow != 0xBEEF){
12474 0 : printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12475 : (unsigned int)pidlow);
12476 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12477 0 : return;
12478 : }
12479 4 : pidhigh = SVAL(phdr, HDR_PIDHIGH);
12480 4 : if (pidhigh != 0xDEAD){
12481 0 : printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12482 : (unsigned int)pidhigh);
12483 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12484 0 : return;
12485 : }
12486 :
12487 4 : tevent_req_done(req);
12488 : }
12489 :
12490 4 : static NTSTATUS pid_echo_recv(struct tevent_req *req)
12491 : {
12492 4 : return tevent_req_simple_recv_ntstatus(req);
12493 : }
12494 :
12495 4 : static bool run_pidhigh(int dummy)
12496 : {
12497 4 : bool success = false;
12498 4 : struct cli_state *cli = NULL;
12499 : NTSTATUS status;
12500 4 : struct tevent_context *ev = NULL;
12501 4 : struct tevent_req *req = NULL;
12502 4 : TALLOC_CTX *frame = talloc_stackframe();
12503 :
12504 4 : printf("starting pid high test\n");
12505 4 : if (!torture_open_connection(&cli, 0)) {
12506 0 : return false;
12507 : }
12508 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12509 :
12510 4 : ev = samba_tevent_context_init(frame);
12511 4 : if (ev == NULL) {
12512 0 : goto fail;
12513 : }
12514 :
12515 4 : req = pid_echo_send(frame, ev, cli);
12516 4 : if (req == NULL) {
12517 0 : goto fail;
12518 : }
12519 :
12520 4 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12521 0 : goto fail;
12522 : }
12523 :
12524 4 : status = pid_echo_recv(req);
12525 4 : if (NT_STATUS_IS_OK(status)) {
12526 4 : printf("pid high test ok\n");
12527 4 : success = true;
12528 : }
12529 :
12530 4 : fail:
12531 :
12532 4 : TALLOC_FREE(frame);
12533 4 : torture_close_connection(cli);
12534 4 : return success;
12535 : }
12536 :
12537 : /*
12538 : Test Windows open on a bad POSIX symlink.
12539 : */
12540 4 : static bool run_symlink_open_test(int dummy)
12541 : {
12542 : static struct cli_state *cli;
12543 4 : const char *fname = "non_existant_file";
12544 4 : const char *sname = "dangling_symlink";
12545 4 : uint16_t fnum = (uint16_t)-1;
12546 4 : bool correct = false;
12547 : NTSTATUS status;
12548 4 : TALLOC_CTX *frame = NULL;
12549 :
12550 4 : frame = talloc_stackframe();
12551 :
12552 4 : printf("Starting Windows bad symlink open test\n");
12553 :
12554 4 : if (!torture_open_connection(&cli, 0)) {
12555 0 : TALLOC_FREE(frame);
12556 0 : return false;
12557 : }
12558 :
12559 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12560 :
12561 4 : status = torture_setup_unix_extensions(cli);
12562 4 : if (!NT_STATUS_IS_OK(status)) {
12563 0 : TALLOC_FREE(frame);
12564 0 : return false;
12565 : }
12566 :
12567 : /* Ensure nothing exists. */
12568 4 : cli_setatr(cli, fname, 0, 0);
12569 4 : cli_posix_unlink(cli, fname);
12570 4 : cli_setatr(cli, sname, 0, 0);
12571 4 : cli_posix_unlink(cli, sname);
12572 :
12573 : /* Create a symlink pointing nowhere. */
12574 4 : status = cli_posix_symlink(cli, fname, sname);
12575 4 : if (!NT_STATUS_IS_OK(status)) {
12576 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12577 : sname,
12578 : fname,
12579 : nt_errstr(status));
12580 0 : goto out;
12581 : }
12582 :
12583 : /* Now ensure that a Windows open doesn't hang. */
12584 4 : status = cli_ntcreate(cli,
12585 : sname,
12586 : 0,
12587 : FILE_READ_DATA|FILE_WRITE_DATA,
12588 : 0,
12589 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12590 : FILE_OPEN_IF,
12591 : 0x0,
12592 : 0x0,
12593 : &fnum,
12594 : NULL);
12595 :
12596 : /*
12597 : * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12598 : * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12599 : * we use O_NOFOLLOW on the server or not.
12600 : */
12601 8 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12602 4 : NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12603 : {
12604 4 : correct = true;
12605 : } else {
12606 0 : printf("cli_ntcreate of %s returned %s - should return"
12607 : " either (%s) or (%s)\n",
12608 : sname,
12609 : nt_errstr(status),
12610 0 : nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12611 0 : nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12612 0 : goto out;
12613 : }
12614 :
12615 4 : correct = true;
12616 :
12617 4 : out:
12618 :
12619 4 : if (fnum != (uint16_t)-1) {
12620 0 : cli_close(cli, fnum);
12621 0 : fnum = (uint16_t)-1;
12622 : }
12623 :
12624 4 : cli_setatr(cli, sname, 0, 0);
12625 4 : cli_posix_unlink(cli, sname);
12626 4 : cli_setatr(cli, fname, 0, 0);
12627 4 : cli_posix_unlink(cli, fname);
12628 :
12629 4 : if (!torture_close_connection(cli)) {
12630 0 : correct = false;
12631 : }
12632 :
12633 4 : TALLOC_FREE(frame);
12634 4 : return correct;
12635 : }
12636 :
12637 16 : static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12638 : const char *name,
12639 : void *state)
12640 : {
12641 16 : char **mangled_name_return = (char **)state;
12642 16 : bool is_mangled = strchr(finfo->name, '~');
12643 :
12644 16 : if (is_mangled) {
12645 8 : *mangled_name_return = talloc_strdup(NULL, finfo->name);
12646 8 : if (*mangled_name_return == NULL) {
12647 0 : return NT_STATUS_NO_MEMORY;
12648 : }
12649 : }
12650 16 : return NT_STATUS_OK;
12651 : }
12652 :
12653 4 : static bool run_smb1_wild_mangle_unlink_test(int dummy)
12654 : {
12655 : static struct cli_state *cli_posix = NULL;
12656 : static struct cli_state *cli = NULL;
12657 4 : uint16_t fnum = (uint16_t)-1;
12658 4 : bool correct = false;
12659 4 : const char *dname = "smb1_wild_mangle_unlink";
12660 4 : const char *aname = "smb1_wild_mangle_unlink/a";
12661 4 : const char *star_name = "smb1_wild_mangle_unlink/*";
12662 4 : char *windows_unlink_name = NULL;
12663 4 : char *mangled_name = NULL;
12664 : NTSTATUS status;
12665 :
12666 4 : printf("Starting SMB1 wild mangle unlink test\n");
12667 :
12668 : /* Open a Windows connection. */
12669 4 : if (!torture_open_connection(&cli, 0)) {
12670 0 : return false;
12671 : }
12672 :
12673 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12674 :
12675 : /* Open a POSIX connection. */
12676 4 : if (!torture_open_connection(&cli_posix, 0)) {
12677 0 : goto out;
12678 : }
12679 :
12680 4 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12681 :
12682 4 : status = torture_setup_unix_extensions(cli_posix);
12683 4 : if (!NT_STATUS_IS_OK(status)) {
12684 0 : printf("server doesn't support POSIX\n");
12685 0 : goto out;
12686 : }
12687 :
12688 : /* Start fresh. */
12689 4 : cli_unlink(cli,
12690 : star_name,
12691 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12692 4 : cli_rmdir(cli, dname);
12693 :
12694 : /*
12695 : * Create two files - 'a' and '*'.
12696 : * We need POSIX extensions for this as '*'
12697 : * is not a valid Windows name.
12698 : */
12699 :
12700 4 : status = cli_mkdir(cli, dname);
12701 4 : if (!NT_STATUS_IS_OK(status)) {
12702 0 : printf("cli_mkdir of %s returned %s\n",
12703 : dname,
12704 : nt_errstr(status));
12705 0 : goto out;
12706 : }
12707 :
12708 4 : status = cli_posix_open(cli_posix,
12709 : aname,
12710 : O_RDWR|O_CREAT|O_EXCL,
12711 : 0660,
12712 : &fnum);
12713 4 : if (!NT_STATUS_IS_OK(status)) {
12714 0 : printf("cli_posix_open (create) of %s returned %s\n",
12715 : aname,
12716 : nt_errstr(status));
12717 0 : goto out;
12718 : }
12719 4 : status = cli_close(cli_posix, fnum);
12720 4 : if (!NT_STATUS_IS_OK(status)) {
12721 0 : goto out;
12722 : }
12723 4 : status = cli_posix_open(cli_posix,
12724 : star_name,
12725 : O_RDWR|O_CREAT|O_EXCL,
12726 : 0660,
12727 : &fnum);
12728 4 : if (!NT_STATUS_IS_OK(status)) {
12729 0 : printf("cli_posix_open (create) of %s returned %s\n",
12730 : star_name,
12731 : nt_errstr(status));
12732 0 : goto out;
12733 : }
12734 4 : status = cli_close(cli_posix, fnum);
12735 4 : if (!NT_STATUS_IS_OK(status)) {
12736 0 : goto out;
12737 : }
12738 :
12739 4 : status = cli_list(cli,
12740 : star_name,
12741 : 0,
12742 : smb1_wild_mangle_list_fn,
12743 : &mangled_name);
12744 4 : if (!NT_STATUS_IS_OK(status)) {
12745 0 : printf("cli_list of %s returned %s\n",
12746 : star_name,
12747 : nt_errstr(status));
12748 0 : goto out;
12749 : }
12750 :
12751 4 : if (mangled_name == NULL) {
12752 0 : goto out;
12753 : }
12754 :
12755 4 : printf("mangled_name = %s\n",
12756 : mangled_name);
12757 :
12758 : /*
12759 : * Try a Windows unlink with the mangled name.
12760 : * This should *NOT* unlink the 'a' name.
12761 : */
12762 :
12763 4 : windows_unlink_name = talloc_asprintf(cli_posix,
12764 : "%s\\%s",
12765 : dname,
12766 : mangled_name);
12767 :
12768 4 : status = cli_unlink(cli, windows_unlink_name, 0);
12769 4 : if (!NT_STATUS_IS_OK(status)) {
12770 0 : printf("cli_unlink of %s returned %s\n",
12771 : windows_unlink_name,
12772 : nt_errstr(status));
12773 0 : goto out;
12774 : }
12775 :
12776 : /* Does 'a' still exist ? */
12777 4 : status = cli_posix_open(cli_posix,
12778 : aname,
12779 : O_RDONLY,
12780 : 0,
12781 : &fnum);
12782 4 : if (!NT_STATUS_IS_OK(status)) {
12783 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
12784 : aname,
12785 : nt_errstr(status));
12786 0 : goto out;
12787 : }
12788 :
12789 4 : status = cli_close(cli_posix, fnum);
12790 4 : if (!NT_STATUS_IS_OK(status)) {
12791 0 : goto out;
12792 : }
12793 :
12794 4 : correct = true;
12795 :
12796 4 : out:
12797 :
12798 4 : TALLOC_FREE(windows_unlink_name);
12799 4 : TALLOC_FREE(mangled_name);
12800 :
12801 4 : if (cli != NULL) {
12802 4 : cli_unlink(cli,
12803 : star_name,
12804 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12805 4 : cli_rmdir(cli, dname);
12806 4 : torture_close_connection(cli);
12807 : }
12808 :
12809 4 : if (cli_posix != NULL) {
12810 4 : torture_close_connection(cli_posix);
12811 : }
12812 :
12813 4 : return correct;
12814 : }
12815 :
12816 4 : static bool run_smb1_wild_mangle_rename_test(int dummy)
12817 : {
12818 : static struct cli_state *cli_posix = NULL;
12819 : static struct cli_state *cli = NULL;
12820 4 : uint16_t fnum = (uint16_t)-1;
12821 4 : bool correct = false;
12822 4 : const char *dname = "smb1_wild_mangle_rename";
12823 4 : const char *fooname = "smb1_wild_mangle_rename/foo";
12824 4 : const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12825 4 : const char *wild_name = "smb1_wild_mangle_rename/*";
12826 4 : char *windows_rename_src = NULL;
12827 4 : const char *windows_rename_dst = "smb1_wild_mangle_rename\\ba*";
12828 4 : char *mangled_name = NULL;
12829 : NTSTATUS status;
12830 :
12831 4 : printf("Starting SMB1 wild mangle rename test\n");
12832 :
12833 4 : if (!torture_open_connection(&cli_posix, 0)) {
12834 0 : return false;
12835 : }
12836 :
12837 4 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12838 :
12839 4 : status = torture_setup_unix_extensions(cli_posix);
12840 4 : if (!NT_STATUS_IS_OK(status)) {
12841 0 : printf("server doesn't support POSIX\n");
12842 0 : return false;
12843 : }
12844 :
12845 : /* Open a Windows connection. */
12846 4 : if (!torture_open_connection(&cli, 0)) {
12847 0 : goto out;
12848 : }
12849 :
12850 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12851 :
12852 : /* Ensure we start from fresh. */
12853 4 : cli_unlink(cli,
12854 : wild_name,
12855 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12856 4 : cli_posix_rmdir(cli_posix, dname);
12857 :
12858 : /*
12859 : * Create two files - 'foo' and 'fo*'.
12860 : * We need POSIX extensions for this as 'fo*'
12861 : * is not a valid Windows name.
12862 : */
12863 :
12864 4 : status = cli_posix_mkdir(cli_posix, dname, 0770);
12865 4 : if (!NT_STATUS_IS_OK(status)) {
12866 0 : printf("cli_posix_mkdir of %s returned %s\n",
12867 : dname,
12868 : nt_errstr(status));
12869 0 : goto out;
12870 : }
12871 :
12872 4 : status = cli_posix_open(cli_posix,
12873 : fooname,
12874 : O_RDWR|O_CREAT|O_EXCL,
12875 : 0660,
12876 : &fnum);
12877 4 : if (!NT_STATUS_IS_OK(status)) {
12878 0 : printf("cli_posix_open (create) of %s returned %s\n",
12879 : fooname,
12880 : nt_errstr(status));
12881 0 : goto out;
12882 : }
12883 4 : status = cli_close(cli_posix, fnum);
12884 4 : if (!NT_STATUS_IS_OK(status)) {
12885 0 : goto out;
12886 : }
12887 4 : status = cli_posix_open(cli_posix,
12888 : foostar_name,
12889 : O_RDWR|O_CREAT|O_EXCL,
12890 : 0660,
12891 : &fnum);
12892 4 : if (!NT_STATUS_IS_OK(status)) {
12893 0 : printf("cli_posix_open (create) of %s returned %s\n",
12894 : foostar_name,
12895 : nt_errstr(status));
12896 0 : goto out;
12897 : }
12898 4 : status = cli_close(cli_posix, fnum);
12899 4 : if (!NT_STATUS_IS_OK(status)) {
12900 0 : goto out;
12901 : }
12902 :
12903 : /*
12904 : * Get the mangled name. We can re-use the
12905 : * previous smb1_wild_mangle_list_fn for this.
12906 : */
12907 :
12908 4 : status = cli_list(cli,
12909 : wild_name,
12910 : 0,
12911 : smb1_wild_mangle_list_fn,
12912 : &mangled_name);
12913 4 : if (!NT_STATUS_IS_OK(status)) {
12914 0 : printf("cli_list of %s returned %s\n",
12915 : wild_name,
12916 : nt_errstr(status));
12917 0 : goto out;
12918 : }
12919 :
12920 4 : if (mangled_name == NULL) {
12921 0 : goto out;
12922 : }
12923 :
12924 4 : printf("mangled_name = %s\n",
12925 : mangled_name);
12926 :
12927 : /*
12928 : * Try a Windows rename with the mangled name.
12929 : * This should *NOT* rename the 'foo' name.
12930 : */
12931 :
12932 4 : windows_rename_src = talloc_asprintf(cli_posix,
12933 : "%s\\%s",
12934 : dname,
12935 : mangled_name);
12936 :
12937 4 : status = cli_rename(cli,
12938 : windows_rename_src,
12939 : windows_rename_dst,
12940 : false);
12941 4 : if (!NT_STATUS_IS_OK(status)) {
12942 0 : printf("cli_rename of %s -> %s returned %s\n",
12943 : windows_rename_src,
12944 : windows_rename_dst,
12945 : nt_errstr(status));
12946 0 : goto out;
12947 : }
12948 :
12949 : /* Does 'foo' still exist ? */
12950 4 : status = cli_posix_open(cli_posix,
12951 : fooname,
12952 : O_RDONLY,
12953 : 0,
12954 : &fnum);
12955 4 : if (!NT_STATUS_IS_OK(status)) {
12956 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
12957 : fooname,
12958 : nt_errstr(status));
12959 0 : goto out;
12960 : }
12961 :
12962 4 : status = cli_close(cli_posix, fnum);
12963 4 : if (!NT_STATUS_IS_OK(status)) {
12964 0 : goto out;
12965 : }
12966 :
12967 4 : correct = true;
12968 :
12969 4 : out:
12970 :
12971 4 : TALLOC_FREE(mangled_name);
12972 4 : TALLOC_FREE(windows_rename_src);
12973 :
12974 4 : if (cli != NULL) {
12975 4 : cli_unlink(cli,
12976 : wild_name,
12977 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12978 4 : torture_close_connection(cli);
12979 : }
12980 :
12981 4 : cli_posix_rmdir(cli_posix, dname);
12982 4 : torture_close_connection(cli_posix);
12983 :
12984 4 : return correct;
12985 : }
12986 :
12987 : /*
12988 : * Only testing minimal time strings, as the others
12989 : * need (locale-dependent) guessing at what strftime does and
12990 : * even may differ in builds.
12991 : */
12992 1 : static bool timesubst_test(void)
12993 : {
12994 1 : TALLOC_CTX *ctx = NULL;
12995 : /* Sa 23. Dez 04:33:20 CET 2017 */
12996 1 : const struct timeval tv = { 1514000000, 123 };
12997 1 : const char* expect_minimal = "20171223_033320";
12998 1 : const char* expect_minus = "20171223_033320_000123";
12999 : char *s;
13000 1 : char *env_tz, *orig_tz = NULL;
13001 1 : bool result = true;
13002 :
13003 1 : ctx = talloc_new(NULL);
13004 :
13005 1 : env_tz = getenv("TZ");
13006 1 : if(env_tz) {
13007 1 : orig_tz = talloc_strdup(ctx, env_tz);
13008 : }
13009 1 : setenv("TZ", "UTC", 1);
13010 :
13011 1 : s = minimal_timeval_string(ctx, &tv, false);
13012 :
13013 1 : if(!s || strcmp(s, expect_minimal)) {
13014 0 : printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13015 : "[%s]\n", s ? s : "<nil>", expect_minimal);
13016 0 : result = false;
13017 : }
13018 1 : TALLOC_FREE(s);
13019 1 : s = minimal_timeval_string(ctx, &tv, true);
13020 1 : if(!s || strcmp(s, expect_minus)) {
13021 0 : printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13022 : "[%s]\n", s ? s : "<nil>", expect_minus);
13023 0 : result = false;
13024 : }
13025 1 : TALLOC_FREE(s);
13026 :
13027 1 : if(orig_tz) {
13028 1 : setenv("TZ", orig_tz, 1);
13029 : }
13030 :
13031 1 : TALLOC_FREE(ctx);
13032 1 : return result;
13033 : }
13034 :
13035 1 : static bool run_local_substitute(int dummy)
13036 : {
13037 1 : bool ok = true;
13038 :
13039 1 : ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13040 1 : ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13041 1 : ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13042 1 : ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13043 1 : ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13044 1 : ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13045 1 : ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13046 1 : ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13047 1 : ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13048 : /* Substitution depends on current time, so better test the underlying
13049 : formatting function. At least covers %t. */
13050 1 : ok &= timesubst_test();
13051 :
13052 : /* Different captialization rules in sub_basic... */
13053 :
13054 2 : ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13055 1 : "blaDOM") == 0);
13056 :
13057 1 : return ok;
13058 : }
13059 :
13060 1 : static bool run_local_base64(int dummy)
13061 : {
13062 : int i;
13063 1 : bool ret = true;
13064 :
13065 2000 : for (i=1; i<2000; i++) {
13066 : DATA_BLOB blob1, blob2;
13067 : char *b64;
13068 :
13069 1999 : blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13070 1999 : blob1.length = i;
13071 1999 : generate_random_buffer(blob1.data, blob1.length);
13072 :
13073 1999 : b64 = base64_encode_data_blob(talloc_tos(), blob1);
13074 1999 : if (b64 == NULL) {
13075 0 : d_fprintf(stderr, "base64_encode_data_blob failed "
13076 : "for %d bytes\n", i);
13077 0 : ret = false;
13078 : }
13079 1999 : blob2 = base64_decode_data_blob(b64);
13080 1999 : TALLOC_FREE(b64);
13081 :
13082 1999 : if (data_blob_cmp(&blob1, &blob2)) {
13083 0 : d_fprintf(stderr, "data_blob_cmp failed for %d "
13084 : "bytes\n", i);
13085 0 : ret = false;
13086 : }
13087 1999 : TALLOC_FREE(blob1.data);
13088 1999 : data_blob_free(&blob2);
13089 : }
13090 1 : return ret;
13091 : }
13092 :
13093 1000000 : static void parse_fn(const struct gencache_timeout *t,
13094 : DATA_BLOB blob,
13095 : void *private_data)
13096 : {
13097 1000000 : return;
13098 : }
13099 :
13100 1 : static bool run_local_gencache(int dummy)
13101 : {
13102 : char *val;
13103 : time_t tm;
13104 : DATA_BLOB blob;
13105 : char v;
13106 : struct memcache *mem;
13107 : int i;
13108 :
13109 1 : mem = memcache_init(NULL, 0);
13110 1 : if (mem == NULL) {
13111 0 : d_printf("%s: memcache_init failed\n", __location__);
13112 0 : return false;
13113 : }
13114 1 : memcache_set_global(mem);
13115 :
13116 1 : if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13117 0 : d_printf("%s: gencache_set() failed\n", __location__);
13118 0 : return False;
13119 : }
13120 :
13121 1 : if (!gencache_get("foo", NULL, NULL, NULL)) {
13122 0 : d_printf("%s: gencache_get() failed\n", __location__);
13123 0 : return False;
13124 : }
13125 :
13126 1000000 : for (i=0; i<1000000; i++) {
13127 1000000 : gencache_parse("foo", parse_fn, NULL);
13128 : }
13129 :
13130 1 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13131 0 : d_printf("%s: gencache_get() failed\n", __location__);
13132 0 : return False;
13133 : }
13134 1 : TALLOC_FREE(val);
13135 :
13136 1 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13137 0 : d_printf("%s: gencache_get() failed\n", __location__);
13138 0 : return False;
13139 : }
13140 :
13141 1 : if (strcmp(val, "bar") != 0) {
13142 0 : d_printf("%s: gencache_get() returned %s, expected %s\n",
13143 : __location__, val, "bar");
13144 0 : TALLOC_FREE(val);
13145 0 : return False;
13146 : }
13147 :
13148 1 : TALLOC_FREE(val);
13149 :
13150 1 : if (!gencache_del("foo")) {
13151 0 : d_printf("%s: gencache_del() failed\n", __location__);
13152 0 : return False;
13153 : }
13154 1 : if (gencache_del("foo")) {
13155 0 : d_printf("%s: second gencache_del() succeeded\n",
13156 : __location__);
13157 0 : return False;
13158 : }
13159 :
13160 1 : if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13161 0 : d_printf("%s: gencache_get() on deleted entry "
13162 : "succeeded\n", __location__);
13163 0 : return False;
13164 : }
13165 :
13166 1 : blob = data_blob_string_const_null("bar");
13167 1 : tm = time(NULL) + 60;
13168 :
13169 1 : if (!gencache_set_data_blob("foo", blob, tm)) {
13170 0 : d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13171 0 : return False;
13172 : }
13173 :
13174 1 : if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13175 0 : d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13176 0 : return False;
13177 : }
13178 :
13179 1 : if (strcmp((const char *)blob.data, "bar") != 0) {
13180 0 : d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13181 0 : __location__, (const char *)blob.data, "bar");
13182 0 : data_blob_free(&blob);
13183 0 : return False;
13184 : }
13185 :
13186 1 : data_blob_free(&blob);
13187 :
13188 1 : if (!gencache_del("foo")) {
13189 0 : d_printf("%s: gencache_del() failed\n", __location__);
13190 0 : return False;
13191 : }
13192 1 : if (gencache_del("foo")) {
13193 0 : d_printf("%s: second gencache_del() succeeded\n",
13194 : __location__);
13195 0 : return False;
13196 : }
13197 :
13198 1 : if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13199 0 : d_printf("%s: gencache_get_data_blob() on deleted entry "
13200 : "succeeded\n", __location__);
13201 0 : return False;
13202 : }
13203 :
13204 1 : v = 1;
13205 1 : blob.data = (uint8_t *)&v;
13206 1 : blob.length = sizeof(v);
13207 :
13208 1 : if (!gencache_set_data_blob("blob", blob, tm)) {
13209 0 : d_printf("%s: gencache_set_data_blob() failed\n",
13210 : __location__);
13211 0 : return false;
13212 : }
13213 1 : if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13214 0 : d_printf("%s: gencache_get succeeded\n", __location__);
13215 0 : return false;
13216 : }
13217 :
13218 0 : return True;
13219 : }
13220 :
13221 1 : static bool rbt_testflags(struct db_context *db, const char *key,
13222 : const char *value)
13223 : {
13224 1 : bool ret = false;
13225 : NTSTATUS status;
13226 : struct db_record *rec;
13227 :
13228 1 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13229 1 : if (rec == NULL) {
13230 0 : d_fprintf(stderr, "fetch_locked failed\n");
13231 0 : goto done;
13232 : }
13233 :
13234 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13235 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13236 0 : d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13237 : nt_errstr(status));
13238 0 : goto done;
13239 : }
13240 :
13241 1 : status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13242 : TDB_INSERT);
13243 1 : if (!NT_STATUS_IS_OK(status)) {
13244 0 : d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13245 : nt_errstr(status));
13246 0 : goto done;
13247 : }
13248 :
13249 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13250 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13251 0 : d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13252 : nt_errstr(status));
13253 0 : goto done;
13254 : }
13255 :
13256 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13257 1 : if (!NT_STATUS_IS_OK(status)) {
13258 0 : d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13259 : nt_errstr(status));
13260 0 : goto done;
13261 : }
13262 :
13263 0 : ret = true;
13264 1 : done:
13265 1 : TALLOC_FREE(rec);
13266 1 : return ret;
13267 : }
13268 :
13269 1998 : static bool rbt_testval(struct db_context *db, const char *key,
13270 : const char *value)
13271 : {
13272 : struct db_record *rec;
13273 1998 : TDB_DATA data = string_tdb_data(value);
13274 1998 : bool ret = false;
13275 : NTSTATUS status;
13276 : TDB_DATA dbvalue;
13277 :
13278 1998 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13279 1998 : if (rec == NULL) {
13280 0 : d_fprintf(stderr, "fetch_locked failed\n");
13281 0 : goto done;
13282 : }
13283 1998 : status = dbwrap_record_store(rec, data, 0);
13284 1998 : if (!NT_STATUS_IS_OK(status)) {
13285 0 : d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13286 0 : goto done;
13287 : }
13288 1998 : TALLOC_FREE(rec);
13289 :
13290 1998 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13291 1998 : if (rec == NULL) {
13292 0 : d_fprintf(stderr, "second fetch_locked failed\n");
13293 0 : goto done;
13294 : }
13295 :
13296 1998 : dbvalue = dbwrap_record_get_value(rec);
13297 1998 : if ((dbvalue.dsize != data.dsize)
13298 1998 : || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13299 0 : d_fprintf(stderr, "Got wrong data back\n");
13300 0 : goto done;
13301 : }
13302 :
13303 0 : ret = true;
13304 1998 : done:
13305 1998 : TALLOC_FREE(rec);
13306 1998 : return ret;
13307 : }
13308 :
13309 1000 : static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13310 : {
13311 1000 : int *count2 = (int *)private_data;
13312 1000 : (*count2)++;
13313 1000 : return 0;
13314 : }
13315 :
13316 1000 : static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13317 : {
13318 1000 : int *count2 = (int *)private_data;
13319 1000 : (*count2)++;
13320 1000 : dbwrap_record_delete(rec);
13321 1000 : return 0;
13322 : }
13323 :
13324 1 : static bool run_local_rbtree(int dummy)
13325 : {
13326 : struct db_context *db;
13327 1 : bool ret = false;
13328 : int i;
13329 : NTSTATUS status;
13330 1 : int count = 0;
13331 1 : int count2 = 0;
13332 :
13333 1 : db = db_open_rbt(NULL);
13334 :
13335 1 : if (db == NULL) {
13336 0 : d_fprintf(stderr, "db_open_rbt failed\n");
13337 0 : return false;
13338 : }
13339 :
13340 1 : if (!rbt_testflags(db, "firstkey", "firstval")) {
13341 0 : goto done;
13342 : }
13343 :
13344 999 : for (i = 0; i < 999; i++) {
13345 : char key[sizeof("key-9223372036854775807")];
13346 : char value[sizeof("value-9223372036854775807")];
13347 :
13348 1998 : snprintf(key, sizeof(key), "key%ld", random());
13349 1998 : snprintf(value, sizeof(value) ,"value%ld", random());
13350 :
13351 999 : if (!rbt_testval(db, key, value)) {
13352 0 : goto done;
13353 : }
13354 :
13355 1998 : snprintf(value, sizeof(value) ,"value%ld", random());
13356 :
13357 999 : if (!rbt_testval(db, key, value)) {
13358 0 : goto done;
13359 : }
13360 : }
13361 :
13362 1 : ret = true;
13363 1 : count = 0; count2 = 0;
13364 1 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13365 : &count2, &count);
13366 2 : printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13367 1 : if ((count != count2) || (count != 1000)) {
13368 0 : ret = false;
13369 : }
13370 1 : count = 0; count2 = 0;
13371 1 : status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13372 : &count2, &count);
13373 2 : printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13374 1 : if ((count != count2) || (count != 1000)) {
13375 0 : ret = false;
13376 : }
13377 1 : count = 0; count2 = 0;
13378 1 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13379 : &count2, &count);
13380 2 : printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13381 1 : if ((count != count2) || (count != 0)) {
13382 0 : ret = false;
13383 : }
13384 :
13385 2 : done:
13386 1 : TALLOC_FREE(db);
13387 1 : return ret;
13388 : }
13389 :
13390 :
13391 : /*
13392 : local test for character set functions
13393 :
13394 : This is a very simple test for the functionality in convert_string_error()
13395 : */
13396 1 : static bool run_local_convert_string(int dummy)
13397 : {
13398 1 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13399 1 : const char *test_strings[2] = { "March", "M\303\244rz" };
13400 : char dst[7];
13401 : int i;
13402 :
13403 6 : for (i=0; i<2; i++) {
13404 2 : const char *str = test_strings[i];
13405 2 : int len = strlen(str);
13406 : size_t converted_size;
13407 : bool ret;
13408 :
13409 2 : memset(dst, 'X', sizeof(dst));
13410 :
13411 : /* first try with real source length */
13412 2 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13413 : str, len,
13414 : dst, sizeof(dst),
13415 : &converted_size);
13416 2 : if (ret != true) {
13417 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13418 0 : goto failed;
13419 : }
13420 :
13421 2 : if (converted_size != len) {
13422 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13423 : str, len, (int)converted_size);
13424 0 : goto failed;
13425 : }
13426 :
13427 2 : if (strncmp(str, dst, converted_size) != 0) {
13428 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13429 0 : goto failed;
13430 : }
13431 :
13432 2 : if (strlen(str) != converted_size) {
13433 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13434 0 : (int)strlen(str), (int)converted_size);
13435 0 : goto failed;
13436 : }
13437 :
13438 2 : if (dst[converted_size] != 'X') {
13439 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13440 0 : goto failed;
13441 : }
13442 :
13443 : /* now with srclen==-1, this causes the nul to be
13444 : * converted too */
13445 2 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13446 : str, -1,
13447 : dst, sizeof(dst),
13448 : &converted_size);
13449 2 : if (ret != true) {
13450 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13451 0 : goto failed;
13452 : }
13453 :
13454 2 : if (converted_size != len+1) {
13455 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13456 : str, len, (int)converted_size);
13457 0 : goto failed;
13458 : }
13459 :
13460 2 : if (strncmp(str, dst, converted_size) != 0) {
13461 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13462 0 : goto failed;
13463 : }
13464 :
13465 0 : if (len+1 != converted_size) {
13466 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13467 : len+1, (int)converted_size);
13468 0 : goto failed;
13469 : }
13470 :
13471 2 : if (dst[converted_size] != 'X') {
13472 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13473 0 : goto failed;
13474 : }
13475 :
13476 : }
13477 :
13478 :
13479 1 : TALLOC_FREE(tmp_ctx);
13480 0 : return true;
13481 0 : failed:
13482 0 : TALLOC_FREE(tmp_ctx);
13483 0 : return false;
13484 : }
13485 :
13486 1 : static bool run_local_string_to_sid(int dummy) {
13487 : struct dom_sid sid;
13488 :
13489 1 : if (string_to_sid(&sid, "S--1-5-32-545")) {
13490 0 : printf("allowing S--1-5-32-545\n");
13491 0 : return false;
13492 : }
13493 1 : if (string_to_sid(&sid, "S-1-5-32-+545")) {
13494 0 : printf("allowing S-1-5-32-+545\n");
13495 0 : return false;
13496 : }
13497 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")) {
13498 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");
13499 0 : return false;
13500 : }
13501 1 : if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13502 0 : printf("allowing S-1-5-32-545-abc\n");
13503 0 : return false;
13504 : }
13505 1 : if (string_to_sid(&sid, "S-300-5-32-545")) {
13506 0 : printf("allowing S-300-5-32-545\n");
13507 0 : return false;
13508 : }
13509 1 : if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13510 0 : printf("allowing S-1-0xfffffffffffffe-32-545\n");
13511 0 : return false;
13512 : }
13513 1 : if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13514 0 : printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13515 0 : return false;
13516 : }
13517 1 : if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13518 0 : printf("could not parse S-1-0xfffffffffffe-32-545\n");
13519 0 : return false;
13520 : }
13521 1 : if (!string_to_sid(&sid, "S-1-5-32-545")) {
13522 0 : printf("could not parse S-1-5-32-545\n");
13523 0 : return false;
13524 : }
13525 1 : if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13526 : struct dom_sid_buf buf;
13527 0 : printf("mis-parsed S-1-5-32-545 as %s\n",
13528 : dom_sid_str_buf(&sid, &buf));
13529 0 : return false;
13530 : }
13531 0 : return true;
13532 : }
13533 :
13534 3 : static bool sid_to_string_test(const char *expected) {
13535 : char *str;
13536 3 : bool res = true;
13537 : struct dom_sid sid;
13538 :
13539 3 : if (!string_to_sid(&sid, expected)) {
13540 0 : printf("could not parse %s\n", expected);
13541 0 : return false;
13542 : }
13543 :
13544 3 : str = dom_sid_string(NULL, &sid);
13545 3 : if (strcmp(str, expected)) {
13546 0 : printf("Comparison failed (%s != %s)\n", str, expected);
13547 0 : res = false;
13548 : }
13549 3 : TALLOC_FREE(str);
13550 3 : return res;
13551 : }
13552 :
13553 1 : static bool run_local_sid_to_string(int dummy) {
13554 1 : if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13555 0 : return false;
13556 1 : if (!sid_to_string_test("S-1-545"))
13557 0 : return false;
13558 1 : if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13559 0 : return false;
13560 1 : return true;
13561 : }
13562 :
13563 1 : static bool run_local_binary_to_sid(int dummy) {
13564 : ssize_t ret;
13565 1 : struct dom_sid *sid = talloc(NULL, struct dom_sid);
13566 : static const uint8_t good_binary_sid[] = {
13567 : 0x1, /* revision number */
13568 : 15, /* num auths */
13569 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13570 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13571 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13572 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13573 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13574 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13575 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13576 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13577 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13578 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13579 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13580 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13581 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13582 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13583 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13584 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13585 : };
13586 :
13587 : static const uint8_t long_binary_sid[] = {
13588 : 0x1, /* revision number */
13589 : 15, /* num auths */
13590 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13591 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13592 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13593 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13594 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13595 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13596 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13597 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13598 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13599 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13600 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13601 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13602 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13603 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13604 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13605 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13606 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13607 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13608 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13609 : };
13610 :
13611 : static const uint8_t long_binary_sid2[] = {
13612 : 0x1, /* revision number */
13613 : 32, /* num auths */
13614 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13615 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13616 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13617 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13618 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13619 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13620 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13621 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13622 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13623 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13624 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13625 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13626 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13627 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13628 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13629 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13630 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13631 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13632 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13633 : 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13634 : 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13635 : 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13636 : 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13637 : 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13638 : 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13639 : 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13640 : 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13641 : 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13642 : 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13643 : 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13644 : 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13645 : 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13646 : 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13647 : };
13648 :
13649 1 : ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13650 1 : if (ret == -1) {
13651 0 : return false;
13652 : }
13653 1 : ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13654 1 : if (ret != -1) {
13655 0 : return false;
13656 : }
13657 1 : ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13658 1 : if (ret != -1) {
13659 0 : return false;
13660 : }
13661 1 : return true;
13662 : }
13663 :
13664 : /* Split a path name into filename and stream name components. Canonicalise
13665 : * such that an implicit $DATA token is always explicit.
13666 : *
13667 : * The "specification" of this function can be found in the
13668 : * run_local_stream_name() function in torture.c, I've tried those
13669 : * combinations against a W2k3 server.
13670 : */
13671 :
13672 8 : static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13673 : char **pbase, char **pstream)
13674 : {
13675 8 : char *base = NULL;
13676 8 : char *stream = NULL;
13677 : char *sname; /* stream name */
13678 : const char *stype; /* stream type */
13679 :
13680 8 : DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13681 :
13682 8 : sname = strchr_m(fname, ':');
13683 :
13684 8 : if (sname == NULL) {
13685 1 : if (pbase != NULL) {
13686 1 : base = talloc_strdup(mem_ctx, fname);
13687 1 : NT_STATUS_HAVE_NO_MEMORY(base);
13688 : }
13689 0 : goto done;
13690 : }
13691 :
13692 7 : if (pbase != NULL) {
13693 7 : base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13694 7 : NT_STATUS_HAVE_NO_MEMORY(base);
13695 : }
13696 :
13697 7 : sname += 1;
13698 :
13699 7 : stype = strchr_m(sname, ':');
13700 :
13701 7 : if (stype == NULL) {
13702 2 : sname = talloc_strdup(mem_ctx, sname);
13703 2 : stype = "$DATA";
13704 : }
13705 : else {
13706 5 : if (strcasecmp_m(stype, ":$DATA") != 0) {
13707 : /*
13708 : * If there is an explicit stream type, so far we only
13709 : * allow $DATA. Is there anything else allowed? -- vl
13710 : */
13711 3 : DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13712 3 : TALLOC_FREE(base);
13713 3 : return NT_STATUS_OBJECT_NAME_INVALID;
13714 : }
13715 2 : sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13716 2 : stype += 1;
13717 : }
13718 :
13719 4 : if (sname == NULL) {
13720 0 : TALLOC_FREE(base);
13721 0 : return NT_STATUS_NO_MEMORY;
13722 : }
13723 :
13724 4 : if (sname[0] == '\0') {
13725 : /*
13726 : * no stream name, so no stream
13727 : */
13728 0 : goto done;
13729 : }
13730 :
13731 3 : if (pstream != NULL) {
13732 3 : stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13733 3 : if (stream == NULL) {
13734 0 : TALLOC_FREE(sname);
13735 0 : TALLOC_FREE(base);
13736 0 : return NT_STATUS_NO_MEMORY;
13737 : }
13738 : /*
13739 : * upper-case the type field
13740 : */
13741 3 : (void)strupper_m(strchr_m(stream, ':')+1);
13742 : }
13743 :
13744 6 : done:
13745 5 : if (pbase != NULL) {
13746 5 : *pbase = base;
13747 : }
13748 5 : if (pstream != NULL) {
13749 5 : *pstream = stream;
13750 : }
13751 5 : return NT_STATUS_OK;
13752 : }
13753 :
13754 8 : static bool test_stream_name(const char *fname, const char *expected_base,
13755 : const char *expected_stream,
13756 : NTSTATUS expected_status)
13757 : {
13758 : NTSTATUS status;
13759 8 : char *base = NULL;
13760 8 : char *stream = NULL;
13761 :
13762 8 : status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13763 8 : if (!NT_STATUS_EQUAL(status, expected_status)) {
13764 0 : goto error;
13765 : }
13766 :
13767 8 : if (!NT_STATUS_IS_OK(status)) {
13768 0 : return true;
13769 : }
13770 :
13771 5 : if (base == NULL) goto error;
13772 :
13773 5 : if (strcmp(expected_base, base) != 0) goto error;
13774 :
13775 5 : if ((expected_stream != NULL) && (stream == NULL)) goto error;
13776 5 : if ((expected_stream == NULL) && (stream != NULL)) goto error;
13777 :
13778 5 : if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13779 0 : goto error;
13780 :
13781 5 : TALLOC_FREE(base);
13782 5 : TALLOC_FREE(stream);
13783 0 : return true;
13784 :
13785 0 : error:
13786 0 : d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13787 : fname, expected_base ? expected_base : "<NULL>",
13788 : expected_stream ? expected_stream : "<NULL>",
13789 : nt_errstr(expected_status));
13790 0 : d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13791 0 : base ? base : "<NULL>", stream ? stream : "<NULL>",
13792 : nt_errstr(status));
13793 0 : TALLOC_FREE(base);
13794 0 : TALLOC_FREE(stream);
13795 0 : return false;
13796 : }
13797 :
13798 1 : static bool run_local_stream_name(int dummy)
13799 : {
13800 1 : bool ret = true;
13801 :
13802 1 : ret &= test_stream_name(
13803 1 : "bla", "bla", NULL, NT_STATUS_OK);
13804 1 : ret &= test_stream_name(
13805 1 : "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13806 1 : ret &= test_stream_name(
13807 1 : "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13808 1 : ret &= test_stream_name(
13809 1 : "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13810 1 : ret &= test_stream_name(
13811 1 : "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13812 1 : ret &= test_stream_name(
13813 1 : "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13814 1 : ret &= test_stream_name(
13815 1 : "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13816 1 : ret &= test_stream_name(
13817 1 : "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13818 :
13819 1 : return ret;
13820 : }
13821 :
13822 2 : static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13823 : {
13824 2 : if (a.length != b.length) {
13825 0 : printf("a.length=%d != b.length=%d\n",
13826 0 : (int)a.length, (int)b.length);
13827 0 : return false;
13828 : }
13829 2 : if (memcmp(a.data, b.data, a.length) != 0) {
13830 0 : printf("a.data and b.data differ\n");
13831 0 : return false;
13832 : }
13833 0 : return true;
13834 : }
13835 :
13836 1 : static bool run_local_memcache(int dummy)
13837 : {
13838 : struct memcache *cache;
13839 : DATA_BLOB k1, k2, k3, k4, k5;
13840 : DATA_BLOB d1, d3;
13841 : DATA_BLOB v1, v3;
13842 :
13843 : TALLOC_CTX *mem_ctx;
13844 1 : char *ptr1 = NULL;
13845 1 : char *ptr2 = NULL;
13846 1 : char *ptr3 = NULL;
13847 :
13848 : char *str1, *str2;
13849 : size_t size1, size2;
13850 1 : bool ret = false;
13851 :
13852 1 : mem_ctx = talloc_init("foo");
13853 1 : if (mem_ctx == NULL) {
13854 0 : return false;
13855 : }
13856 :
13857 : /* STAT_CACHE TESTS */
13858 :
13859 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13860 :
13861 1 : if (cache == NULL) {
13862 0 : printf("memcache_init failed\n");
13863 0 : return false;
13864 : }
13865 :
13866 1 : d1 = data_blob_const("d1", 2);
13867 1 : d3 = data_blob_const("d3", 2);
13868 :
13869 1 : k1 = data_blob_const("d1", 2);
13870 1 : k2 = data_blob_const("d2", 2);
13871 1 : k3 = data_blob_const("d3", 2);
13872 1 : k4 = data_blob_const("d4", 2);
13873 1 : k5 = data_blob_const("d5", 2);
13874 :
13875 1 : memcache_add(cache, STAT_CACHE, k1, d1);
13876 :
13877 1 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13878 0 : printf("could not find k1\n");
13879 0 : return false;
13880 : }
13881 1 : if (!data_blob_equal(d1, v1)) {
13882 0 : return false;
13883 : }
13884 :
13885 1 : memcache_add(cache, STAT_CACHE, k1, d3);
13886 :
13887 1 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13888 0 : printf("could not find replaced k1\n");
13889 0 : return false;
13890 : }
13891 1 : if (!data_blob_equal(d3, v3)) {
13892 0 : return false;
13893 : }
13894 :
13895 1 : TALLOC_FREE(cache);
13896 :
13897 : /* GETWD_CACHE TESTS */
13898 1 : str1 = talloc_strdup(mem_ctx, "string1");
13899 1 : if (str1 == NULL) {
13900 0 : return false;
13901 : }
13902 1 : ptr2 = str1; /* Keep an alias for comparison. */
13903 :
13904 1 : str2 = talloc_strdup(mem_ctx, "string2");
13905 1 : if (str2 == NULL) {
13906 0 : return false;
13907 : }
13908 :
13909 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13910 1 : if (cache == NULL) {
13911 0 : printf("memcache_init failed\n");
13912 0 : return false;
13913 : }
13914 :
13915 1 : memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
13916 : /* str1 == NULL now. */
13917 1 : ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13918 1 : if (ptr1 == NULL) {
13919 0 : printf("could not find k2\n");
13920 0 : return false;
13921 : }
13922 1 : if (ptr1 != ptr2) {
13923 0 : printf("fetch of k2 got wrong string\n");
13924 0 : return false;
13925 : }
13926 :
13927 : /* Add a blob to ensure k2 gets purged. */
13928 1 : d3 = data_blob_talloc_zero(mem_ctx, 180);
13929 1 : memcache_add(cache, STAT_CACHE, k3, d3);
13930 :
13931 1 : ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13932 1 : if (ptr2 != NULL) {
13933 0 : printf("Did find k2, should have been purged\n");
13934 0 : return false;
13935 : }
13936 :
13937 : /*
13938 : * Test that talloc size also is accounted in memcache and
13939 : * causes purge of other object.
13940 : */
13941 :
13942 1 : str1 = talloc_zero_size(mem_ctx, 100);
13943 1 : str2 = talloc_zero_size(mem_ctx, 100);
13944 :
13945 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13946 1 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
13947 :
13948 1 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13949 1 : if (ptr3 != NULL) {
13950 0 : printf("Did find k4, should have been purged\n");
13951 0 : return false;
13952 : }
13953 :
13954 : /*
13955 : * Test that adding a duplicate non-talloced
13956 : * key/value on top of a talloced key/value takes account
13957 : * of the talloc_freed value size.
13958 : */
13959 1 : TALLOC_FREE(cache);
13960 1 : TALLOC_FREE(mem_ctx);
13961 :
13962 1 : mem_ctx = talloc_init("key_replace");
13963 1 : if (mem_ctx == NULL) {
13964 0 : return false;
13965 : }
13966 :
13967 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13968 1 : if (cache == NULL) {
13969 0 : return false;
13970 : }
13971 :
13972 : /*
13973 : * Add a 100 byte talloced string. This will
13974 : * store a (4 or 8 byte) pointer and record the
13975 : * total talloced size.
13976 : */
13977 1 : str1 = talloc_zero_size(mem_ctx, 100);
13978 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13979 : /*
13980 : * Now overwrite with a small talloced
13981 : * value. This should fit in the existing size
13982 : * and the total talloced size should be removed
13983 : * from the cache size.
13984 : */
13985 1 : str1 = talloc_zero_size(mem_ctx, 2);
13986 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13987 : /*
13988 : * Now store a 20 byte string. If the
13989 : * total talloced size wasn't accounted for
13990 : * and removed in the overwrite, then this
13991 : * will evict k4.
13992 : */
13993 1 : str2 = talloc_zero_size(mem_ctx, 20);
13994 1 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
13995 :
13996 1 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13997 1 : if (ptr3 == NULL) {
13998 0 : printf("Did not find k4, should not have been purged\n");
13999 0 : return false;
14000 : }
14001 :
14002 1 : TALLOC_FREE(cache);
14003 1 : TALLOC_FREE(mem_ctx);
14004 :
14005 1 : mem_ctx = talloc_init("foo");
14006 1 : if (mem_ctx == NULL) {
14007 0 : return false;
14008 : }
14009 :
14010 1 : cache = memcache_init(NULL, 0);
14011 1 : if (cache == NULL) {
14012 0 : return false;
14013 : }
14014 :
14015 1 : str1 = talloc_strdup(mem_ctx, "string1");
14016 1 : if (str1 == NULL) {
14017 0 : return false;
14018 : }
14019 1 : str2 = talloc_strdup(mem_ctx, "string2");
14020 1 : if (str2 == NULL) {
14021 0 : return false;
14022 : }
14023 1 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14024 : data_blob_string_const("torture"), &str1);
14025 1 : size1 = talloc_total_size(cache);
14026 :
14027 1 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14028 : data_blob_string_const("torture"), &str2);
14029 1 : size2 = talloc_total_size(cache);
14030 :
14031 2 : printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14032 :
14033 1 : if (size2 > size1) {
14034 0 : printf("memcache leaks memory!\n");
14035 0 : goto fail;
14036 : }
14037 :
14038 0 : ret = true;
14039 1 : fail:
14040 1 : TALLOC_FREE(cache);
14041 1 : return ret;
14042 : }
14043 :
14044 200 : static void wbclient_done(struct tevent_req *req)
14045 : {
14046 : wbcErr wbc_err;
14047 : struct winbindd_response *wb_resp;
14048 200 : int *i = (int *)tevent_req_callback_data_void(req);
14049 :
14050 200 : wbc_err = wb_trans_recv(req, req, &wb_resp);
14051 200 : TALLOC_FREE(req);
14052 200 : *i += 1;
14053 200 : d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14054 200 : }
14055 :
14056 2 : static bool run_wbclient_multi_ping(int dummy)
14057 : {
14058 : struct tevent_context *ev;
14059 : struct wb_context **wb_ctx;
14060 : struct winbindd_request wb_req;
14061 2 : bool result = false;
14062 : int i, j;
14063 :
14064 2 : BlockSignals(True, SIGPIPE);
14065 :
14066 2 : ev = tevent_context_init(talloc_tos());
14067 2 : if (ev == NULL) {
14068 0 : goto fail;
14069 : }
14070 :
14071 2 : wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14072 2 : if (wb_ctx == NULL) {
14073 0 : goto fail;
14074 : }
14075 :
14076 2 : ZERO_STRUCT(wb_req);
14077 2 : wb_req.cmd = WINBINDD_PING;
14078 :
14079 2 : d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14080 :
14081 4 : for (i=0; i<torture_nprocs; i++) {
14082 2 : wb_ctx[i] = wb_context_init(ev, NULL);
14083 2 : if (wb_ctx[i] == NULL) {
14084 0 : goto fail;
14085 : }
14086 202 : for (j=0; j<torture_numops; j++) {
14087 : struct tevent_req *req;
14088 200 : req = wb_trans_send(ev, ev, wb_ctx[i],
14089 200 : (j % 2) == 0, &wb_req);
14090 200 : if (req == NULL) {
14091 0 : goto fail;
14092 : }
14093 200 : tevent_req_set_callback(req, wbclient_done, &i);
14094 : }
14095 : }
14096 :
14097 2 : i = 0;
14098 :
14099 819 : while (i < torture_nprocs * torture_numops) {
14100 816 : tevent_loop_once(ev);
14101 : }
14102 :
14103 2 : result = true;
14104 2 : fail:
14105 2 : TALLOC_FREE(ev);
14106 2 : return result;
14107 : }
14108 :
14109 0 : static bool dbtrans_inc(struct db_context *db)
14110 : {
14111 : struct db_record *rec;
14112 : uint32_t val;
14113 0 : bool ret = false;
14114 : NTSTATUS status;
14115 : TDB_DATA value;
14116 :
14117 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14118 0 : if (rec == NULL) {
14119 0 : printf(__location__ "fetch_lock failed\n");
14120 0 : return false;
14121 : }
14122 :
14123 0 : value = dbwrap_record_get_value(rec);
14124 :
14125 0 : if (value.dsize != sizeof(uint32_t)) {
14126 0 : printf(__location__ "value.dsize = %d\n",
14127 0 : (int)value.dsize);
14128 0 : goto fail;
14129 : }
14130 :
14131 0 : memcpy(&val, value.dptr, sizeof(val));
14132 0 : val += 1;
14133 :
14134 0 : status = dbwrap_record_store(
14135 : rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14136 0 : if (!NT_STATUS_IS_OK(status)) {
14137 0 : printf(__location__ "store failed: %s\n",
14138 : nt_errstr(status));
14139 0 : goto fail;
14140 : }
14141 :
14142 0 : ret = true;
14143 0 : fail:
14144 0 : TALLOC_FREE(rec);
14145 0 : return ret;
14146 : }
14147 :
14148 0 : static bool run_local_dbtrans(int dummy)
14149 : {
14150 : struct db_context *db;
14151 : struct db_record *rec;
14152 : NTSTATUS status;
14153 : uint32_t initial;
14154 : int res;
14155 : TDB_DATA value;
14156 :
14157 0 : db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14158 : O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14159 : DBWRAP_FLAG_NONE);
14160 0 : if (db == NULL) {
14161 0 : printf("Could not open transtest.db\n");
14162 0 : return false;
14163 : }
14164 :
14165 0 : res = dbwrap_transaction_start(db);
14166 0 : if (res != 0) {
14167 0 : printf(__location__ "transaction_start failed\n");
14168 0 : return false;
14169 : }
14170 :
14171 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14172 0 : if (rec == NULL) {
14173 0 : printf(__location__ "fetch_lock failed\n");
14174 0 : return false;
14175 : }
14176 :
14177 0 : value = dbwrap_record_get_value(rec);
14178 :
14179 0 : if (value.dptr == NULL) {
14180 0 : initial = 0;
14181 0 : status = dbwrap_record_store(
14182 : rec, make_tdb_data((uint8_t *)&initial,
14183 : sizeof(initial)),
14184 : 0);
14185 0 : if (!NT_STATUS_IS_OK(status)) {
14186 0 : printf(__location__ "store returned %s\n",
14187 : nt_errstr(status));
14188 0 : return false;
14189 : }
14190 : }
14191 :
14192 0 : TALLOC_FREE(rec);
14193 :
14194 0 : res = dbwrap_transaction_commit(db);
14195 0 : if (res != 0) {
14196 0 : printf(__location__ "transaction_commit failed\n");
14197 0 : return false;
14198 : }
14199 :
14200 0 : while (true) {
14201 : uint32_t val, val2;
14202 : int i;
14203 :
14204 0 : res = dbwrap_transaction_start(db);
14205 0 : if (res != 0) {
14206 0 : printf(__location__ "transaction_start failed\n");
14207 0 : break;
14208 : }
14209 :
14210 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14211 0 : if (!NT_STATUS_IS_OK(status)) {
14212 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14213 : nt_errstr(status));
14214 0 : break;
14215 : }
14216 :
14217 0 : for (i=0; i<10; i++) {
14218 0 : if (!dbtrans_inc(db)) {
14219 0 : return false;
14220 : }
14221 : }
14222 :
14223 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14224 0 : if (!NT_STATUS_IS_OK(status)) {
14225 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14226 : nt_errstr(status));
14227 0 : break;
14228 : }
14229 :
14230 0 : if (val2 != val + 10) {
14231 0 : printf(__location__ "val=%d, val2=%d\n",
14232 : (int)val, (int)val2);
14233 0 : break;
14234 : }
14235 :
14236 0 : printf("val2=%d\r", val2);
14237 :
14238 0 : res = dbwrap_transaction_commit(db);
14239 0 : if (res != 0) {
14240 0 : printf(__location__ "transaction_commit failed\n");
14241 0 : break;
14242 : }
14243 : }
14244 :
14245 0 : TALLOC_FREE(db);
14246 0 : return true;
14247 : }
14248 :
14249 : /*
14250 : * Just a dummy test to be run under a debugger. There's no real way
14251 : * to inspect the tevent_poll specific function from outside of
14252 : * tevent_poll.c.
14253 : */
14254 :
14255 1 : static bool run_local_tevent_poll(int dummy)
14256 : {
14257 : struct tevent_context *ev;
14258 : struct tevent_fd *fd1, *fd2;
14259 1 : bool result = false;
14260 :
14261 1 : ev = tevent_context_init_byname(NULL, "poll");
14262 1 : if (ev == NULL) {
14263 0 : d_fprintf(stderr, "tevent_context_init_byname failed\n");
14264 0 : goto fail;
14265 : }
14266 :
14267 1 : fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14268 1 : if (fd1 == NULL) {
14269 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14270 0 : goto fail;
14271 : }
14272 1 : fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14273 1 : if (fd2 == NULL) {
14274 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14275 0 : goto fail;
14276 : }
14277 1 : TALLOC_FREE(fd2);
14278 :
14279 1 : fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14280 1 : if (fd2 == NULL) {
14281 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14282 0 : goto fail;
14283 : }
14284 :
14285 0 : result = true;
14286 1 : fail:
14287 1 : TALLOC_FREE(ev);
14288 1 : return result;
14289 : }
14290 :
14291 1 : static bool run_local_hex_encode_buf(int dummy)
14292 : {
14293 : char buf[17];
14294 : uint8_t src[8];
14295 : int i;
14296 :
14297 9 : for (i=0; i<sizeof(src); i++) {
14298 8 : src[i] = i;
14299 : }
14300 1 : hex_encode_buf(buf, src, sizeof(src));
14301 1 : if (strcmp(buf, "0001020304050607") != 0) {
14302 0 : return false;
14303 : }
14304 1 : hex_encode_buf(buf, NULL, 0);
14305 1 : if (buf[0] != '\0') {
14306 0 : return false;
14307 : }
14308 1 : return true;
14309 : }
14310 :
14311 : static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14312 : "0.0.0.0",
14313 : "::0",
14314 : "1.2.3.1",
14315 : "0.0.0.0",
14316 : "0.0.0.0",
14317 : "1.2.3.2",
14318 : "1.2.3.3",
14319 : "1.2.3.4",
14320 : "1.2.3.5",
14321 : "::0",
14322 : "1.2.3.6",
14323 : "1.2.3.7",
14324 : "::0",
14325 : "::0",
14326 : "::0",
14327 : "1.2.3.8",
14328 : "1.2.3.9",
14329 : "1.2.3.10",
14330 : "1.2.3.11",
14331 : "1.2.3.12",
14332 : "1.2.3.13",
14333 : "1001:1111:1111:1000:0:1111:1111:1111",
14334 : "1.2.3.1",
14335 : "1.2.3.2",
14336 : "1.2.3.3",
14337 : "1.2.3.12",
14338 : "::0",
14339 : "::0"
14340 : };
14341 :
14342 : static const char *remove_duplicate_addrs2_test_strings_result[] = {
14343 : "1.2.3.1",
14344 : "1.2.3.2",
14345 : "1.2.3.3",
14346 : "1.2.3.4",
14347 : "1.2.3.5",
14348 : "1.2.3.6",
14349 : "1.2.3.7",
14350 : "1.2.3.8",
14351 : "1.2.3.9",
14352 : "1.2.3.10",
14353 : "1.2.3.11",
14354 : "1.2.3.12",
14355 : "1.2.3.13",
14356 : "1001:1111:1111:1000:0:1111:1111:1111"
14357 : };
14358 :
14359 1 : static bool run_local_remove_duplicate_addrs2(int dummy)
14360 : {
14361 : struct samba_sockaddr test_vector[28];
14362 : size_t count, i;
14363 :
14364 : /* Construct the sockaddr_storage test vector. */
14365 29 : for (i = 0; i < 28; i++) {
14366 : struct addrinfo hints;
14367 28 : struct addrinfo *res = NULL;
14368 : int ret;
14369 :
14370 28 : memset(&hints, '\0', sizeof(hints));
14371 28 : hints.ai_flags = AI_NUMERICHOST;
14372 28 : ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14373 : NULL,
14374 : &hints,
14375 : &res);
14376 28 : if (ret) {
14377 0 : fprintf(stderr, "getaddrinfo failed on [%s]\n",
14378 : remove_duplicate_addrs2_test_strings_vector[i]);
14379 0 : return false;
14380 : }
14381 56 : memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14382 84 : memcpy(&test_vector[i].u.ss,
14383 28 : res->ai_addr,
14384 28 : res->ai_addrlen);
14385 28 : freeaddrinfo(res);
14386 : }
14387 :
14388 1 : count = remove_duplicate_addrs2(test_vector, i);
14389 :
14390 1 : if (count != 14) {
14391 0 : fprintf(stderr, "count wrong (%zu) should be 14\n",
14392 : count);
14393 0 : return false;
14394 : }
14395 :
14396 14 : for (i = 0; i < count; i++) {
14397 : char addr[INET6_ADDRSTRLEN];
14398 :
14399 14 : print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14400 :
14401 14 : if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14402 0 : fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14403 : i,
14404 : addr,
14405 : remove_duplicate_addrs2_test_strings_result[i]);
14406 0 : return false;
14407 : }
14408 : }
14409 :
14410 1 : printf("run_local_remove_duplicate_addrs2: success\n");
14411 1 : return true;
14412 : }
14413 :
14414 0 : static bool run_local_tdb_opener(int dummy)
14415 : {
14416 : TDB_CONTEXT *t;
14417 0 : unsigned v = 0;
14418 :
14419 : while (1) {
14420 0 : t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14421 : O_RDWR|O_CREAT, 0755);
14422 0 : if (t == NULL) {
14423 0 : perror("tdb_open failed");
14424 0 : return false;
14425 : }
14426 0 : tdb_close(t);
14427 :
14428 0 : v += 1;
14429 0 : printf("\r%u", v);
14430 : }
14431 : return true;
14432 : }
14433 :
14434 0 : static bool run_local_tdb_writer(int dummy)
14435 : {
14436 : TDB_CONTEXT *t;
14437 0 : unsigned v = 0;
14438 : TDB_DATA val;
14439 :
14440 0 : t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14441 0 : if (t == 0) {
14442 0 : perror("tdb_open failed");
14443 0 : return 1;
14444 : }
14445 :
14446 0 : val.dptr = (uint8_t *)&v;
14447 0 : val.dsize = sizeof(v);
14448 :
14449 0 : while (1) {
14450 : TDB_DATA data;
14451 : int ret;
14452 :
14453 0 : ret = tdb_store(t, val, val, 0);
14454 0 : if (ret != 0) {
14455 0 : printf("%s\n", tdb_errorstr(t));
14456 : }
14457 0 : v += 1;
14458 0 : printf("\r%u", v);
14459 :
14460 0 : data = tdb_fetch(t, val);
14461 0 : if (data.dptr != NULL) {
14462 0 : SAFE_FREE(data.dptr);
14463 : }
14464 : }
14465 : return true;
14466 : }
14467 :
14468 1 : static bool run_local_canonicalize_path(int dummy)
14469 : {
14470 1 : const char *src[] = {
14471 : "/foo/..",
14472 : "/..",
14473 : "/foo/bar/../baz",
14474 : "/foo/././",
14475 : "/../foo",
14476 : ".././././",
14477 : ".././././../../../boo",
14478 : "./..",
14479 : "/",
14480 : "/../../",
14481 : "/foo/../",
14482 : "/./././",
14483 : "/./././.",
14484 : "/.../././.",
14485 : "/./././.foo",
14486 : "/./././.foo.",
14487 : "/./././foo.",
14488 : "/foo/bar/..",
14489 : "/foo/bar/../baz/",
14490 : "////////////////",
14491 : "/////////./././././.",
14492 : "/./.././../.boo/../baz",
14493 : "/a/component/path",
14494 : "/a/component/path/",
14495 : "/a/component/path/..",
14496 : "/a/component/../path/",
14497 : "///a/./././///component/../////path/",
14498 : NULL
14499 : };
14500 1 : const char *dst[] = {
14501 : "/",
14502 : "/",
14503 : "/foo/baz",
14504 : "/foo",
14505 : "/foo",
14506 : "/",
14507 : "/boo",
14508 : "/",
14509 : "/",
14510 : "/",
14511 : "/",
14512 : "/",
14513 : "/",
14514 : "/...",
14515 : "/.foo",
14516 : "/.foo.",
14517 : "/foo.",
14518 : "/foo",
14519 : "/foo/baz",
14520 : "/",
14521 : "/",
14522 : "/baz",
14523 : "/a/component/path",
14524 : "/a/component/path",
14525 : "/a/component",
14526 : "/a/path",
14527 : "/a/path",
14528 : NULL
14529 : };
14530 : unsigned int i;
14531 :
14532 28 : for (i = 0; src[i] != NULL; i++) {
14533 27 : char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14534 27 : if (d == NULL) {
14535 0 : perror("talloc fail\n");
14536 0 : return false;
14537 : }
14538 27 : if (strcmp(d, dst[i]) != 0) {
14539 0 : d_fprintf(stderr,
14540 : "canonicalize mismatch %s -> %s != %s",
14541 : src[i], d, dst[i]);
14542 0 : return false;
14543 : }
14544 27 : talloc_free(d);
14545 : }
14546 0 : return true;
14547 : }
14548 :
14549 0 : static bool run_ign_bad_negprot(int dummy)
14550 : {
14551 : struct tevent_context *ev;
14552 : struct tevent_req *req;
14553 : struct smbXcli_conn *conn;
14554 : struct sockaddr_storage ss;
14555 : NTSTATUS status;
14556 : int fd;
14557 : bool ok;
14558 :
14559 0 : printf("starting ignore bad negprot\n");
14560 :
14561 0 : ok = resolve_name(host, &ss, 0x20, true);
14562 0 : if (!ok) {
14563 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
14564 0 : return false;
14565 : }
14566 :
14567 0 : status = open_socket_out(&ss, 445, 10000, &fd);
14568 0 : if (!NT_STATUS_IS_OK(status)) {
14569 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
14570 : nt_errstr(status));
14571 0 : return false;
14572 : }
14573 :
14574 0 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14575 : NULL, 0, NULL);
14576 0 : if (conn == NULL) {
14577 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
14578 0 : return false;
14579 : }
14580 :
14581 0 : status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14582 0 : if (NT_STATUS_IS_OK(status)) {
14583 0 : d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14584 0 : return false;
14585 : }
14586 :
14587 0 : ev = samba_tevent_context_init(talloc_tos());
14588 0 : if (ev == NULL) {
14589 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
14590 0 : return false;
14591 : }
14592 :
14593 0 : req = smb1cli_session_setup_nt1_send(
14594 0 : ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14595 : data_blob_null, data_blob_null, 0x40,
14596 : "Windows 2000 2195", "Windows 2000 5.0");
14597 0 : if (req == NULL) {
14598 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14599 0 : return false;
14600 : }
14601 :
14602 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
14603 0 : if (!ok) {
14604 0 : d_fprintf(stderr, "tevent_req_poll failed\n");
14605 0 : return false;
14606 : }
14607 :
14608 0 : status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14609 : NULL, NULL);
14610 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14611 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14612 : "%s, expected NT_STATUS_CONNECTION_RESET\n",
14613 : nt_errstr(status));
14614 0 : return false;
14615 : }
14616 :
14617 0 : TALLOC_FREE(conn);
14618 :
14619 0 : printf("starting ignore bad negprot\n");
14620 :
14621 0 : return true;
14622 : }
14623 :
14624 16 : static double create_procs(bool (*fn)(int), bool *result)
14625 : {
14626 : int i, status;
14627 : volatile pid_t *child_status;
14628 : volatile bool *child_status_out;
14629 : int synccount;
14630 16 : int tries = 8;
14631 : struct timeval start;
14632 :
14633 16 : synccount = 0;
14634 :
14635 16 : child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14636 16 : if (!child_status) {
14637 0 : printf("Failed to setup shared memory\n");
14638 0 : return -1;
14639 : }
14640 :
14641 16 : child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14642 16 : if (!child_status_out) {
14643 0 : printf("Failed to setup result status shared memory\n");
14644 0 : return -1;
14645 : }
14646 :
14647 32 : for (i = 0; i < torture_nprocs; i++) {
14648 16 : child_status[i] = 0;
14649 16 : child_status_out[i] = True;
14650 : }
14651 :
14652 16 : start = timeval_current();
14653 :
14654 32 : for (i=0;i<torture_nprocs;i++) {
14655 16 : procnum = i;
14656 16 : if (fork() == 0) {
14657 0 : pid_t mypid = getpid();
14658 0 : sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14659 :
14660 0 : slprintf(myname,sizeof(myname),"CLIENT%d", i);
14661 :
14662 : while (1) {
14663 0 : if (torture_open_connection(¤t_cli, i)) break;
14664 0 : if (tries-- == 0) {
14665 0 : printf("pid %d failed to start\n", (int)getpid());
14666 0 : _exit(1);
14667 : }
14668 0 : smb_msleep(10);
14669 : }
14670 :
14671 0 : child_status[i] = getpid();
14672 :
14673 0 : while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14674 :
14675 0 : child_status_out[i] = fn(i);
14676 0 : _exit(0);
14677 : }
14678 : }
14679 :
14680 : do {
14681 206 : synccount = 0;
14682 412 : for (i=0;i<torture_nprocs;i++) {
14683 206 : if (child_status[i]) synccount++;
14684 : }
14685 206 : if (synccount == torture_nprocs) break;
14686 190 : smb_msleep(10);
14687 190 : } while (timeval_elapsed(&start) < 30);
14688 :
14689 16 : if (synccount != torture_nprocs) {
14690 0 : printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14691 0 : *result = False;
14692 0 : return timeval_elapsed(&start);
14693 : }
14694 :
14695 : /* start the client load */
14696 16 : start = timeval_current();
14697 :
14698 32 : for (i=0;i<torture_nprocs;i++) {
14699 16 : child_status[i] = 0;
14700 : }
14701 :
14702 16 : printf("%d clients started\n", torture_nprocs);
14703 :
14704 32 : for (i=0;i<torture_nprocs;i++) {
14705 16 : while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14706 : }
14707 :
14708 16 : printf("\n");
14709 :
14710 32 : for (i=0;i<torture_nprocs;i++) {
14711 16 : if (!child_status_out[i]) {
14712 2 : *result = False;
14713 : }
14714 : }
14715 16 : return timeval_elapsed(&start);
14716 : }
14717 :
14718 : #define FLAG_MULTIPROC 1
14719 :
14720 : static struct {
14721 : const char *name;
14722 : bool (*fn)(int);
14723 : unsigned flags;
14724 : } torture_ops[] = {
14725 : {
14726 : .name = "FDPASS",
14727 : .fn = run_fdpasstest,
14728 : },
14729 : {
14730 : .name = "LOCK1",
14731 : .fn = run_locktest1,
14732 : },
14733 : {
14734 : .name = "LOCK2",
14735 : .fn = run_locktest2,
14736 : },
14737 : {
14738 : .name = "LOCK3",
14739 : .fn = run_locktest3,
14740 : },
14741 : {
14742 : .name = "LOCK4",
14743 : .fn = run_locktest4,
14744 : },
14745 : {
14746 : .name = "LOCK5",
14747 : .fn = run_locktest5,
14748 : },
14749 : {
14750 : .name = "LOCK6",
14751 : .fn = run_locktest6,
14752 : },
14753 : {
14754 : .name = "LOCK7",
14755 : .fn = run_locktest7,
14756 : },
14757 : {
14758 : .name = "LOCK8",
14759 : .fn = run_locktest8,
14760 : },
14761 : {
14762 : .name = "LOCK9A",
14763 : .fn = run_locktest9a,
14764 : },
14765 : {
14766 : .name = "LOCK9B",
14767 : .fn = run_locktest9b,
14768 : },
14769 : {
14770 : .name = "LOCK10",
14771 : .fn = run_locktest10,
14772 : },
14773 : {
14774 : .name = "LOCK11",
14775 : .fn = run_locktest11,
14776 : },
14777 : {
14778 : .name = "LOCK12",
14779 : .fn = run_locktest12,
14780 : },
14781 : {
14782 : .name = "LOCK13",
14783 : .fn = run_locktest13,
14784 : },
14785 : {
14786 : .name = "UNLINK",
14787 : .fn = run_unlinktest,
14788 : },
14789 : {
14790 : .name = "BROWSE",
14791 : .fn = run_browsetest,
14792 : },
14793 : {
14794 : .name = "ATTR",
14795 : .fn = run_attrtest,
14796 : },
14797 : {
14798 : .name = "TRANS2",
14799 : .fn = run_trans2test,
14800 : },
14801 : {
14802 : .name = "MAXFID",
14803 : .fn = run_maxfidtest,
14804 : .flags = FLAG_MULTIPROC,
14805 : },
14806 : {
14807 : .name = "TORTURE",
14808 : .fn = run_torture,
14809 : .flags = FLAG_MULTIPROC,
14810 : },
14811 : {
14812 : .name = "RANDOMIPC",
14813 : .fn = run_randomipc,
14814 : },
14815 : {
14816 : .name = "NEGNOWAIT",
14817 : .fn = run_negprot_nowait,
14818 : },
14819 : {
14820 : .name = "NBENCH",
14821 : .fn = run_nbench,
14822 : },
14823 : {
14824 : .name = "NBENCH2",
14825 : .fn = run_nbench2,
14826 : },
14827 : {
14828 : .name = "OPLOCK1",
14829 : .fn = run_oplock1,
14830 : },
14831 : {
14832 : .name = "OPLOCK2",
14833 : .fn = run_oplock2,
14834 : },
14835 : {
14836 : .name = "OPLOCK4",
14837 : .fn = run_oplock4,
14838 : },
14839 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14840 : {
14841 : .name = "OPLOCK5",
14842 : .fn = run_oplock5,
14843 : },
14844 : #endif
14845 : {
14846 : .name = "DIR",
14847 : .fn = run_dirtest,
14848 : },
14849 : {
14850 : .name = "DIR1",
14851 : .fn = run_dirtest1,
14852 : },
14853 : {
14854 : .name = "DIR-CREATETIME",
14855 : .fn = run_dir_createtime,
14856 : },
14857 : {
14858 : .name = "DENY1",
14859 : .fn = torture_denytest1,
14860 : },
14861 : {
14862 : .name = "DENY2",
14863 : .fn = torture_denytest2,
14864 : },
14865 : {
14866 : .name = "TCON",
14867 : .fn = run_tcon_test,
14868 : },
14869 : {
14870 : .name = "TCONDEV",
14871 : .fn = run_tcon_devtype_test,
14872 : },
14873 : {
14874 : .name = "RW1",
14875 : .fn = run_readwritetest,
14876 : },
14877 : {
14878 : .name = "RW2",
14879 : .fn = run_readwritemulti,
14880 : .flags = FLAG_MULTIPROC
14881 : },
14882 : {
14883 : .name = "RW3",
14884 : .fn = run_readwritelarge,
14885 : },
14886 : {
14887 : .name = "RW-SIGNING",
14888 : .fn = run_readwritelarge_signtest,
14889 : },
14890 : {
14891 : .name = "OPEN",
14892 : .fn = run_opentest,
14893 : },
14894 : {
14895 : .name = "POSIX",
14896 : .fn = run_simple_posix_open_test,
14897 : },
14898 : {
14899 : .name = "POSIX-APPEND",
14900 : .fn = run_posix_append,
14901 : },
14902 : {
14903 : .name = "POSIX-SYMLINK-ACL",
14904 : .fn = run_acl_symlink_test,
14905 : },
14906 : {
14907 : .name = "POSIX-SYMLINK-EA",
14908 : .fn = run_ea_symlink_test,
14909 : },
14910 : {
14911 : .name = "POSIX-STREAM-DELETE",
14912 : .fn = run_posix_stream_delete,
14913 : },
14914 : {
14915 : .name = "POSIX-OFD-LOCK",
14916 : .fn = run_posix_ofd_lock_test,
14917 : },
14918 : {
14919 : .name = "POSIX-BLOCKING-LOCK",
14920 : .fn = run_posix_blocking_lock,
14921 : },
14922 : {
14923 : .name = "POSIX-MKDIR",
14924 : .fn = run_posix_mkdir_test,
14925 : },
14926 : {
14927 : .name = "POSIX-ACL-OPLOCK",
14928 : .fn = run_posix_acl_oplock_test,
14929 : },
14930 : {
14931 : .name = "POSIX-ACL-SHAREROOT",
14932 : .fn = run_posix_acl_shareroot_test,
14933 : },
14934 : {
14935 : .name = "POSIX-LS-WILDCARD",
14936 : .fn = run_posix_ls_wildcard_test,
14937 : },
14938 : {
14939 : .name = "POSIX-LS-SINGLE",
14940 : .fn = run_posix_ls_single_test,
14941 : },
14942 : {
14943 : .name = "POSIX-READLINK",
14944 : .fn = run_posix_readlink_test,
14945 : },
14946 : {
14947 : .name = "POSIX-STAT",
14948 : .fn = run_posix_stat_test,
14949 : },
14950 : {
14951 : .name = "POSIX-SYMLINK-PARENT",
14952 : .fn = run_posix_symlink_parent_test,
14953 : },
14954 : {
14955 : .name = "POSIX-SYMLINK-CHMOD",
14956 : .fn = run_posix_symlink_chmod_test,
14957 : },
14958 : {
14959 : .name = "POSIX-SYMLINK-RENAME",
14960 : .fn = run_posix_symlink_rename_test,
14961 : },
14962 : {
14963 : .name = "POSIX-DIR-DEFAULT-ACL",
14964 : .fn = run_posix_dir_default_acl_test,
14965 : },
14966 : {
14967 : .name = "POSIX-SYMLINK-GETPATHINFO",
14968 : .fn = run_posix_symlink_getpathinfo_test,
14969 : },
14970 : {
14971 : .name = "POSIX-SYMLINK-SETPATHINFO",
14972 : .fn = run_posix_symlink_setpathinfo_test,
14973 : },
14974 : {
14975 : .name = "WINDOWS-BAD-SYMLINK",
14976 : .fn = run_symlink_open_test,
14977 : },
14978 : {
14979 : .name = "SMB1-WILD-MANGLE-UNLINK",
14980 : .fn = run_smb1_wild_mangle_unlink_test,
14981 : },
14982 : {
14983 : .name = "SMB1-WILD-MANGLE-RENAME",
14984 : .fn = run_smb1_wild_mangle_rename_test,
14985 : },
14986 : {
14987 : .name = "CASE-INSENSITIVE-CREATE",
14988 : .fn = run_case_insensitive_create,
14989 : },
14990 : {
14991 : .name = "ASYNC-ECHO",
14992 : .fn = run_async_echo,
14993 : },
14994 : {
14995 : .name = "UID-REGRESSION-TEST",
14996 : .fn = run_uid_regression_test,
14997 : },
14998 : {
14999 : .name = "SHORTNAME-TEST",
15000 : .fn = run_shortname_test,
15001 : },
15002 : {
15003 : .name = "ADDRCHANGE",
15004 : .fn = run_addrchange,
15005 : },
15006 : #if 1
15007 : {
15008 : .name = "OPENATTR",
15009 : .fn = run_openattrtest,
15010 : },
15011 : #endif
15012 : {
15013 : .name = "XCOPY",
15014 : .fn = run_xcopy,
15015 : },
15016 : {
15017 : .name = "RENAME",
15018 : .fn = run_rename,
15019 : },
15020 : {
15021 : .name = "RENAME-ACCESS",
15022 : .fn = run_rename_access,
15023 : },
15024 : {
15025 : .name = "OWNER-RIGHTS",
15026 : .fn = run_owner_rights,
15027 : },
15028 : {
15029 : .name = "DELETE",
15030 : .fn = run_deletetest,
15031 : },
15032 : {
15033 : .name = "DELETE-STREAM",
15034 : .fn = run_delete_stream,
15035 : },
15036 : {
15037 : .name = "DELETE-PRINT",
15038 : .fn = run_delete_print_test,
15039 : },
15040 : {
15041 : .name = "WILDDELETE",
15042 : .fn = run_wild_deletetest,
15043 : },
15044 : {
15045 : .name = "DELETE-LN",
15046 : .fn = run_deletetest_ln,
15047 : },
15048 : {
15049 : .name = "PROPERTIES",
15050 : .fn = run_properties,
15051 : },
15052 : {
15053 : .name = "MANGLE",
15054 : .fn = torture_mangle,
15055 : },
15056 : {
15057 : .name = "MANGLE1",
15058 : .fn = run_mangle1,
15059 : },
15060 : {
15061 : .name = "MANGLE-ILLEGAL",
15062 : .fn = run_mangle_illegal,
15063 : },
15064 : {
15065 : .name = "W2K",
15066 : .fn = run_w2ktest,
15067 : },
15068 : {
15069 : .name = "TRANS2SCAN",
15070 : .fn = torture_trans2_scan,
15071 : },
15072 : {
15073 : .name = "NTTRANSSCAN",
15074 : .fn = torture_nttrans_scan,
15075 : },
15076 : {
15077 : .name = "UTABLE",
15078 : .fn = torture_utable,
15079 : },
15080 : {
15081 : .name = "CASETABLE",
15082 : .fn = torture_casetable,
15083 : },
15084 : {
15085 : .name = "ERRMAPEXTRACT",
15086 : .fn = run_error_map_extract,
15087 : },
15088 : {
15089 : .name = "PIPE_NUMBER",
15090 : .fn = run_pipe_number,
15091 : },
15092 : {
15093 : .name = "TCON2",
15094 : .fn = run_tcon2_test,
15095 : },
15096 : {
15097 : .name = "IOCTL",
15098 : .fn = torture_ioctl_test,
15099 : },
15100 : {
15101 : .name = "CHKPATH",
15102 : .fn = torture_chkpath_test,
15103 : },
15104 : {
15105 : .name = "FDSESS",
15106 : .fn = run_fdsesstest,
15107 : },
15108 : {
15109 : .name = "EATEST",
15110 : .fn = run_eatest,
15111 : },
15112 : {
15113 : .name = "SESSSETUP_BENCH",
15114 : .fn = run_sesssetup_bench,
15115 : },
15116 : {
15117 : .name = "CHAIN1",
15118 : .fn = run_chain1,
15119 : },
15120 : {
15121 : .name = "CHAIN2",
15122 : .fn = run_chain2,
15123 : },
15124 : {
15125 : .name = "CHAIN3",
15126 : .fn = run_chain3,
15127 : },
15128 : {
15129 : .name = "WINDOWS-WRITE",
15130 : .fn = run_windows_write,
15131 : },
15132 : {
15133 : .name = "LARGE_READX",
15134 : .fn = run_large_readx,
15135 : },
15136 : {
15137 : .name = "MSDFS-ATTRIBUTE",
15138 : .fn = run_msdfs_attribute,
15139 : },
15140 : {
15141 : .name = "NTTRANS-CREATE",
15142 : .fn = run_nttrans_create,
15143 : },
15144 : {
15145 : .name = "NTTRANS-FSCTL",
15146 : .fn = run_nttrans_fsctl,
15147 : },
15148 : {
15149 : .name = "CLI_ECHO",
15150 : .fn = run_cli_echo,
15151 : },
15152 : {
15153 : .name = "CLI_SPLICE",
15154 : .fn = run_cli_splice,
15155 : },
15156 : {
15157 : .name = "TLDAP",
15158 : .fn = run_tldap,
15159 : },
15160 : {
15161 : .name = "STREAMERROR",
15162 : .fn = run_streamerror,
15163 : },
15164 : {
15165 : .name = "NOTIFY-BENCH",
15166 : .fn = run_notify_bench,
15167 : },
15168 : {
15169 : .name = "NOTIFY-BENCH2",
15170 : .fn = run_notify_bench2,
15171 : },
15172 : {
15173 : .name = "NOTIFY-BENCH3",
15174 : .fn = run_notify_bench3,
15175 : },
15176 : {
15177 : .name = "BAD-NBT-SESSION",
15178 : .fn = run_bad_nbt_session,
15179 : },
15180 : {
15181 : .name = "IGN-BAD-NEGPROT",
15182 : .fn = run_ign_bad_negprot,
15183 : },
15184 : {
15185 : .name = "SMB-ANY-CONNECT",
15186 : .fn = run_smb_any_connect,
15187 : },
15188 : {
15189 : .name = "NOTIFY-ONLINE",
15190 : .fn = run_notify_online,
15191 : },
15192 : {
15193 : .name = "SMB2-BASIC",
15194 : .fn = run_smb2_basic,
15195 : },
15196 : {
15197 : .name = "SMB2-NEGPROT",
15198 : .fn = run_smb2_negprot,
15199 : },
15200 : {
15201 : .name = "SMB2-ANONYMOUS",
15202 : .fn = run_smb2_anonymous,
15203 : },
15204 : {
15205 : .name = "SMB2-SESSION-RECONNECT",
15206 : .fn = run_smb2_session_reconnect,
15207 : },
15208 : {
15209 : .name = "SMB2-TCON-DEPENDENCE",
15210 : .fn = run_smb2_tcon_dependence,
15211 : },
15212 : {
15213 : .name = "SMB2-MULTI-CHANNEL",
15214 : .fn = run_smb2_multi_channel,
15215 : },
15216 : {
15217 : .name = "SMB2-SESSION-REAUTH",
15218 : .fn = run_smb2_session_reauth,
15219 : },
15220 : {
15221 : .name = "SMB2-FTRUNCATE",
15222 : .fn = run_smb2_ftruncate,
15223 : },
15224 : {
15225 : .name = "SMB2-DIR-FSYNC",
15226 : .fn = run_smb2_dir_fsync,
15227 : },
15228 : {
15229 : .name = "SMB2-PATH-SLASH",
15230 : .fn = run_smb2_path_slash,
15231 : },
15232 : {
15233 : .name = "SMB1-SYSTEM-SECURITY",
15234 : .fn = run_smb1_system_security,
15235 : },
15236 : {
15237 : .name = "SMB2-SACL",
15238 : .fn = run_smb2_sacl,
15239 : },
15240 : {
15241 : .name = "SMB2-QUOTA1",
15242 : .fn = run_smb2_quota1,
15243 : },
15244 : {
15245 : .name = "SMB2-STREAM-ACL",
15246 : .fn = run_smb2_stream_acl,
15247 : },
15248 : {
15249 : .name = "SMB2-LIST-DIR-ASYNC",
15250 : .fn = run_list_dir_async_test,
15251 : },
15252 : {
15253 : .name = "CLEANUP1",
15254 : .fn = run_cleanup1,
15255 : },
15256 : {
15257 : .name = "CLEANUP2",
15258 : .fn = run_cleanup2,
15259 : },
15260 : {
15261 : .name = "CLEANUP4",
15262 : .fn = run_cleanup4,
15263 : },
15264 : {
15265 : .name = "OPLOCK-CANCEL",
15266 : .fn = run_oplock_cancel,
15267 : },
15268 : {
15269 : .name = "PIDHIGH",
15270 : .fn = run_pidhigh,
15271 : },
15272 : {
15273 : .name = "LOCAL-SUBSTITUTE",
15274 : .fn = run_local_substitute,
15275 : },
15276 : {
15277 : .name = "LOCAL-GENCACHE",
15278 : .fn = run_local_gencache,
15279 : },
15280 : {
15281 : .name = "LOCAL-DBWRAP-WATCH1",
15282 : .fn = run_dbwrap_watch1,
15283 : },
15284 : {
15285 : .name = "LOCAL-DBWRAP-WATCH2",
15286 : .fn = run_dbwrap_watch2,
15287 : },
15288 : {
15289 : .name = "LOCAL-DBWRAP-WATCH3",
15290 : .fn = run_dbwrap_watch3,
15291 : },
15292 : {
15293 : .name = "LOCAL-DBWRAP-WATCH4",
15294 : .fn = run_dbwrap_watch4,
15295 : },
15296 : {
15297 : .name = "LOCAL-DBWRAP-DO-LOCKED1",
15298 : .fn = run_dbwrap_do_locked1,
15299 : },
15300 : {
15301 : .name = "LOCAL-MESSAGING-READ1",
15302 : .fn = run_messaging_read1,
15303 : },
15304 : {
15305 : .name = "LOCAL-MESSAGING-READ2",
15306 : .fn = run_messaging_read2,
15307 : },
15308 : {
15309 : .name = "LOCAL-MESSAGING-READ3",
15310 : .fn = run_messaging_read3,
15311 : },
15312 : {
15313 : .name = "LOCAL-MESSAGING-READ4",
15314 : .fn = run_messaging_read4,
15315 : },
15316 : {
15317 : .name = "LOCAL-MESSAGING-FDPASS1",
15318 : .fn = run_messaging_fdpass1,
15319 : },
15320 : {
15321 : .name = "LOCAL-MESSAGING-FDPASS2",
15322 : .fn = run_messaging_fdpass2,
15323 : },
15324 : {
15325 : .name = "LOCAL-MESSAGING-FDPASS2a",
15326 : .fn = run_messaging_fdpass2a,
15327 : },
15328 : {
15329 : .name = "LOCAL-MESSAGING-FDPASS2b",
15330 : .fn = run_messaging_fdpass2b,
15331 : },
15332 : {
15333 : .name = "LOCAL-MESSAGING-SEND-ALL",
15334 : .fn = run_messaging_send_all,
15335 : },
15336 : {
15337 : .name = "LOCAL-BASE64",
15338 : .fn = run_local_base64,
15339 : },
15340 : {
15341 : .name = "LOCAL-RBTREE",
15342 : .fn = run_local_rbtree,
15343 : },
15344 : {
15345 : .name = "LOCAL-MEMCACHE",
15346 : .fn = run_local_memcache,
15347 : },
15348 : {
15349 : .name = "LOCAL-STREAM-NAME",
15350 : .fn = run_local_stream_name,
15351 : },
15352 : {
15353 : .name = "LOCAL-STR-MATCH-MSWILD",
15354 : .fn = run_str_match_mswild,
15355 : },
15356 : {
15357 : .name = "LOCAL-STR-MATCH-REGEX-SUB1",
15358 : .fn = run_str_match_regex_sub1,
15359 : },
15360 : {
15361 : .name = "WBCLIENT-MULTI-PING",
15362 : .fn = run_wbclient_multi_ping,
15363 : },
15364 : {
15365 : .name = "LOCAL-string_to_sid",
15366 : .fn = run_local_string_to_sid,
15367 : },
15368 : {
15369 : .name = "LOCAL-sid_to_string",
15370 : .fn = run_local_sid_to_string,
15371 : },
15372 : {
15373 : .name = "LOCAL-binary_to_sid",
15374 : .fn = run_local_binary_to_sid,
15375 : },
15376 : {
15377 : .name = "LOCAL-DBTRANS",
15378 : .fn = run_local_dbtrans,
15379 : },
15380 : {
15381 : .name = "LOCAL-TEVENT-POLL",
15382 : .fn = run_local_tevent_poll,
15383 : },
15384 : {
15385 : .name = "LOCAL-CONVERT-STRING",
15386 : .fn = run_local_convert_string,
15387 : },
15388 : {
15389 : .name = "LOCAL-CONV-AUTH-INFO",
15390 : .fn = run_local_conv_auth_info,
15391 : },
15392 : {
15393 : .name = "LOCAL-hex_encode_buf",
15394 : .fn = run_local_hex_encode_buf,
15395 : },
15396 : {
15397 : .name = "LOCAL-IDMAP-TDB-COMMON",
15398 : .fn = run_idmap_tdb_common_test,
15399 : },
15400 : {
15401 : .name = "LOCAL-remove_duplicate_addrs2",
15402 : .fn = run_local_remove_duplicate_addrs2,
15403 : },
15404 : {
15405 : .name = "local-tdb-opener",
15406 : .fn = run_local_tdb_opener,
15407 : },
15408 : {
15409 : .name = "local-tdb-writer",
15410 : .fn = run_local_tdb_writer,
15411 : },
15412 : {
15413 : .name = "LOCAL-DBWRAP-CTDB1",
15414 : .fn = run_local_dbwrap_ctdb1,
15415 : },
15416 : {
15417 : .name = "LOCAL-BENCH-PTHREADPOOL",
15418 : .fn = run_bench_pthreadpool,
15419 : },
15420 : {
15421 : .name = "LOCAL-PTHREADPOOL-TEVENT",
15422 : .fn = run_pthreadpool_tevent,
15423 : },
15424 : {
15425 : .name = "LOCAL-G-LOCK1",
15426 : .fn = run_g_lock1,
15427 : },
15428 : {
15429 : .name = "LOCAL-G-LOCK2",
15430 : .fn = run_g_lock2,
15431 : },
15432 : {
15433 : .name = "LOCAL-G-LOCK3",
15434 : .fn = run_g_lock3,
15435 : },
15436 : {
15437 : .name = "LOCAL-G-LOCK4",
15438 : .fn = run_g_lock4,
15439 : },
15440 : {
15441 : .name = "LOCAL-G-LOCK4A",
15442 : .fn = run_g_lock4a,
15443 : },
15444 : {
15445 : .name = "LOCAL-G-LOCK5",
15446 : .fn = run_g_lock5,
15447 : },
15448 : {
15449 : .name = "LOCAL-G-LOCK6",
15450 : .fn = run_g_lock6,
15451 : },
15452 : {
15453 : .name = "LOCAL-G-LOCK7",
15454 : .fn = run_g_lock7,
15455 : },
15456 : {
15457 : .name = "LOCAL-G-LOCK8",
15458 : .fn = run_g_lock8,
15459 : },
15460 : {
15461 : .name = "LOCAL-G-LOCK-PING-PONG",
15462 : .fn = run_g_lock_ping_pong,
15463 : },
15464 : {
15465 : .name = "LOCAL-CANONICALIZE-PATH",
15466 : .fn = run_local_canonicalize_path,
15467 : },
15468 : {
15469 : .name = "LOCAL-NAMEMAP-CACHE1",
15470 : .fn = run_local_namemap_cache1,
15471 : },
15472 : {
15473 : .name = "LOCAL-IDMAP-CACHE1",
15474 : .fn = run_local_idmap_cache1,
15475 : },
15476 : {
15477 : .name = "qpathinfo-bufsize",
15478 : .fn = run_qpathinfo_bufsize,
15479 : },
15480 : {
15481 : .name = "hide-new-files-timeout",
15482 : .fn = run_hidenewfiles,
15483 : },
15484 : #ifdef CLUSTER_SUPPORT
15485 : {
15486 : .name = "ctdbd-conn1",
15487 : .fn = run_ctdbd_conn1,
15488 : },
15489 : #endif
15490 : {
15491 : .name = "readdir-timestamp",
15492 : .fn = run_readdir_timestamp,
15493 : },
15494 : {
15495 : .name = NULL,
15496 : },
15497 : };
15498 :
15499 : /****************************************************************************
15500 : run a specified test or "ALL"
15501 : ****************************************************************************/
15502 520 : static bool run_test(const char *name)
15503 : {
15504 520 : bool ret = True;
15505 520 : bool result = True;
15506 520 : bool found = False;
15507 : int i;
15508 : double t;
15509 520 : if (strequal(name,"ALL")) {
15510 0 : for (i=0;torture_ops[i].name;i++) {
15511 0 : run_test(torture_ops[i].name);
15512 : }
15513 0 : found = True;
15514 : }
15515 :
15516 98923 : for (i=0;torture_ops[i].name;i++) {
15517 98443 : fstr_sprintf(randomfname, "\\XX%x",
15518 98443 : (unsigned)random());
15519 :
15520 98443 : if (strequal(name, torture_ops[i].name)) {
15521 520 : found = True;
15522 520 : printf("Running %s\n", name);
15523 520 : if (torture_ops[i].flags & FLAG_MULTIPROC) {
15524 16 : t = create_procs(torture_ops[i].fn, &result);
15525 16 : if (!result) {
15526 2 : ret = False;
15527 2 : printf("TEST %s FAILED!\n", name);
15528 : }
15529 : } else {
15530 : struct timeval start;
15531 504 : start = timeval_current();
15532 504 : if (!torture_ops[i].fn(0)) {
15533 10 : ret = False;
15534 10 : printf("TEST %s FAILED!\n", name);
15535 : }
15536 508 : t = timeval_elapsed(&start);
15537 : }
15538 476 : printf("%s took %g secs\n\n", name, t);
15539 : }
15540 : }
15541 :
15542 524 : if (!found) {
15543 0 : printf("Did not find a test named %s\n", name);
15544 0 : ret = False;
15545 : }
15546 :
15547 524 : return ret;
15548 : }
15549 :
15550 :
15551 0 : static void usage(void)
15552 : {
15553 : int i;
15554 :
15555 0 : printf("WARNING samba4 test suite is much more complete nowadays.\n");
15556 0 : printf("Please use samba4 torture.\n\n");
15557 :
15558 0 : printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15559 :
15560 0 : printf("\t-d debuglevel\n");
15561 0 : printf("\t-U user%%pass\n");
15562 0 : printf("\t-k use kerberos\n");
15563 0 : printf("\t-N numprocs\n");
15564 0 : printf("\t-n my_netbios_name\n");
15565 0 : printf("\t-W workgroup\n");
15566 0 : printf("\t-o num_operations\n");
15567 0 : printf("\t-O socket_options\n");
15568 0 : printf("\t-m maximum protocol\n");
15569 0 : printf("\t-L use oplocks\n");
15570 0 : printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
15571 0 : printf("\t-A showall\n");
15572 0 : printf("\t-p port\n");
15573 0 : printf("\t-s seed\n");
15574 0 : printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
15575 0 : printf("\t-f filename filename to test\n");
15576 0 : printf("\t-e encrypt\n");
15577 0 : printf("\n\n");
15578 :
15579 0 : printf("tests are:");
15580 0 : for (i=0;torture_ops[i].name;i++) {
15581 0 : printf(" %s", torture_ops[i].name);
15582 : }
15583 0 : printf("\n");
15584 :
15585 0 : printf("default test is ALL\n");
15586 :
15587 0 : exit(1);
15588 : }
15589 :
15590 : /****************************************************************************
15591 : main program
15592 : ****************************************************************************/
15593 520 : int main(int argc,char *argv[])
15594 : {
15595 : int opt, i;
15596 : char *p;
15597 520 : int gotuser = 0;
15598 520 : int gotpass = 0;
15599 520 : bool correct = True;
15600 520 : TALLOC_CTX *frame = talloc_stackframe();
15601 520 : int seed = time(NULL);
15602 :
15603 : #ifdef HAVE_SETBUFFER
15604 520 : setbuffer(stdout, NULL, 0);
15605 : #endif
15606 :
15607 520 : setup_logging("smbtorture", DEBUG_STDOUT);
15608 :
15609 520 : smb_init_locale();
15610 520 : fault_setup();
15611 :
15612 520 : if (is_default_dyn_CONFIGFILE()) {
15613 520 : if(getenv("SMB_CONF_PATH")) {
15614 520 : set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15615 : }
15616 : }
15617 520 : lp_load_global(get_dyn_CONFIGFILE());
15618 520 : load_interfaces();
15619 :
15620 520 : if (argc < 2) {
15621 0 : usage();
15622 : }
15623 :
15624 10373 : for(p = argv[1]; *p; p++)
15625 9853 : if(*p == '\\')
15626 0 : *p = '/';
15627 :
15628 520 : if (strncmp(argv[1], "//", 2)) {
15629 0 : usage();
15630 : }
15631 :
15632 520 : fstrcpy(host, &argv[1][2]);
15633 520 : p = strchr_m(&host[2],'/');
15634 520 : if (!p) {
15635 0 : usage();
15636 : }
15637 520 : *p = 0;
15638 520 : fstrcpy(share, p+1);
15639 :
15640 520 : fstrcpy(myname, get_myname(talloc_tos()));
15641 520 : if (!*myname) {
15642 0 : fprintf(stderr, "Failed to get my hostname.\n");
15643 0 : return 1;
15644 : }
15645 :
15646 520 : if (*username == 0 && getenv("LOGNAME")) {
15647 0 : fstrcpy(username,getenv("LOGNAME"));
15648 : }
15649 :
15650 520 : argc--;
15651 520 : argv++;
15652 :
15653 520 : fstrcpy(workgroup, lp_workgroup());
15654 :
15655 2215 : while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15656 9 : != EOF) {
15657 1179 : switch (opt) {
15658 0 : case 'p':
15659 0 : port_to_use = atoi(optarg);
15660 0 : break;
15661 0 : case 's':
15662 0 : seed = atoi(optarg);
15663 0 : break;
15664 0 : case 'W':
15665 0 : fstrcpy(workgroup,optarg);
15666 0 : break;
15667 9 : case 'm':
15668 9 : lp_set_cmdline("client max protocol", optarg);
15669 9 : break;
15670 0 : case 'N':
15671 0 : torture_nprocs = atoi(optarg);
15672 0 : break;
15673 0 : case 'o':
15674 0 : torture_numops = atoi(optarg);
15675 0 : break;
15676 0 : case 'd':
15677 0 : lp_set_cmdline("log level", optarg);
15678 0 : break;
15679 0 : case 'O':
15680 0 : sockops = optarg;
15681 0 : break;
15682 0 : case 'L':
15683 0 : use_oplocks = True;
15684 0 : break;
15685 462 : case 'l':
15686 462 : local_path = optarg;
15687 462 : break;
15688 0 : case 'A':
15689 0 : torture_showall = True;
15690 0 : break;
15691 0 : case 'n':
15692 0 : fstrcpy(myname, optarg);
15693 0 : break;
15694 0 : case 'c':
15695 0 : client_txt = optarg;
15696 0 : break;
15697 184 : case 'e':
15698 184 : do_encrypt = true;
15699 184 : break;
15700 0 : case 'k':
15701 : #ifdef HAVE_KRB5
15702 0 : use_kerberos = True;
15703 : #else
15704 : d_printf("No kerberos support compiled in\n");
15705 : exit(1);
15706 : #endif
15707 0 : break;
15708 520 : case 'U':
15709 520 : gotuser = 1;
15710 520 : fstrcpy(username,optarg);
15711 520 : p = strchr_m(username,'%');
15712 520 : if (p) {
15713 520 : *p = 0;
15714 520 : fstrcpy(password, p+1);
15715 520 : gotpass = 1;
15716 : }
15717 476 : break;
15718 0 : case 'b':
15719 0 : fstrcpy(multishare_conn_fname, optarg);
15720 0 : use_multishare_conn = True;
15721 0 : break;
15722 0 : case 'B':
15723 0 : torture_blocksize = atoi(optarg);
15724 0 : break;
15725 4 : case 'f':
15726 4 : test_filename = SMB_STRDUP(optarg);
15727 4 : break;
15728 0 : default:
15729 0 : printf("Unknown option %c (%d)\n", (char)opt, opt);
15730 0 : usage();
15731 : }
15732 : }
15733 :
15734 520 : d_printf("using seed %d\n", seed);
15735 :
15736 520 : srandom(seed);
15737 :
15738 520 : if(use_kerberos && !gotuser) gotpass = True;
15739 :
15740 992 : while (!gotpass) {
15741 0 : char pwd[256] = {0};
15742 : int rc;
15743 :
15744 0 : rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15745 0 : if (rc == 0) {
15746 0 : fstrcpy(password, pwd);
15747 0 : gotpass = 1;
15748 : }
15749 : }
15750 :
15751 520 : printf("host=%s share=%s user=%s myname=%s\n",
15752 : host, share, username, myname);
15753 :
15754 520 : torture_creds = cli_session_creds_init(frame,
15755 : username,
15756 : workgroup,
15757 : NULL, /* realm */
15758 : password,
15759 : use_kerberos,
15760 : false, /* fallback_after_kerberos */
15761 : false, /* use_ccache */
15762 : false); /* password_is_nt_hash */
15763 520 : if (torture_creds == NULL) {
15764 0 : d_printf("cli_session_creds_init() failed.\n");
15765 0 : exit(1);
15766 : }
15767 :
15768 520 : if (argc == optind) {
15769 0 : correct = run_test("ALL");
15770 : } else {
15771 1000 : for (i=optind;i<argc;i++) {
15772 520 : if (!run_test(argv[i])) {
15773 12 : correct = False;
15774 : }
15775 : }
15776 : }
15777 :
15778 524 : TALLOC_FREE(frame);
15779 :
15780 524 : if (correct) {
15781 464 : return(0);
15782 : } else {
15783 12 : return(1);
15784 : }
15785 : }
|