Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Copyright (C) Ralph Boehme 2020
4 :
5 : This program is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as published by
7 : the Free Software Foundation; either version 3 of the License, or
8 : (at your option) any later version.
9 :
10 : This program is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public License
16 : along with this program. If not, see <http://www.gnu.org/licenses/>.
17 : */
18 :
19 : #include "includes.h"
20 : #include "torture/proto.h"
21 : #include "libcli/security/security.h"
22 : #include "libsmb/libsmb.h"
23 : #include "libsmb/clirap.h"
24 : #include "libsmb/proto.h"
25 : #include "../libcli/smb/smbXcli_base.h"
26 : #include "util_sd.h"
27 : #include "trans2.h"
28 :
29 : extern struct cli_credentials *torture_creds;
30 : extern fstring host, workgroup, share, password, username, myname;
31 :
32 : struct posix_test_entry {
33 : const char *name;
34 : const char *target;
35 : const char *expected;
36 : uint32_t attr;
37 : uint64_t returned_size;
38 : bool ok;
39 : };
40 :
41 0 : static NTSTATUS posix_ls_fn(struct file_info *finfo,
42 : const char *name,
43 : void *_state)
44 : {
45 0 : struct posix_test_entry *state =
46 : (struct posix_test_entry *)_state;
47 :
48 0 : for (; state->name != NULL; state++) {
49 0 : if (strequal(finfo->name, state->expected)) {
50 0 : if (state->attr != finfo->attr) {
51 0 : break;
52 : }
53 0 : state->ok = true;
54 0 : state->returned_size = finfo->size;
55 0 : break;
56 : }
57 : }
58 :
59 0 : return NT_STATUS_OK;
60 : }
61 :
62 0 : static void posix_test_entries_reset(struct posix_test_entry *state)
63 : {
64 0 : for (; state->name != NULL; state++) {
65 0 : state->ok = false;
66 0 : state->returned_size = 0;
67 : }
68 0 : }
69 :
70 0 : static bool posix_test_entry_check(struct posix_test_entry *state,
71 : const char *name,
72 : bool expected,
73 : uint64_t expected_size)
74 : {
75 0 : bool result = false;
76 :
77 0 : for (; state->name != NULL; state++) {
78 0 : if (strequal(name, state->name)) {
79 0 : result = state->ok;
80 0 : break;
81 : }
82 : }
83 0 : if (state->name == NULL) {
84 0 : printf("test failed, unknown name: %s\n", name);
85 0 : return false;
86 : }
87 :
88 0 : if (expected == result) {
89 0 : return true;
90 : }
91 :
92 0 : printf("test failed, %s: %s\n",
93 : expected ? "missing" : "unexpected",
94 : name);
95 :
96 0 : return false;
97 : }
98 :
99 : /*
100 : Test non-POSIX vs POSIX ls * of symlinks
101 : */
102 0 : bool run_posix_ls_wildcard_test(int dummy)
103 : {
104 0 : TALLOC_CTX *frame = NULL;
105 0 : struct cli_state *cli_unix = NULL;
106 0 : struct cli_state *cli_win = NULL;
107 0 : uint16_t fnum = (uint16_t)-1;
108 : NTSTATUS status;
109 0 : const char *file = "file";
110 0 : const char *symlnk_dangling = "dangling";
111 0 : const char *symlnk_dst_dangling = "xxxxxxx";
112 0 : const char *symlnk_in_share = "symlnk_in_share";
113 0 : const char *symlnk_dst_in_share = file;
114 0 : const char *symlnk_outside_share = "symlnk_outside_share";
115 0 : const char *symlnk_dst_outside_share = "/etc/passwd";
116 0 : struct posix_test_entry state[] = {
117 : {
118 : .name = symlnk_dangling,
119 : .target = symlnk_dst_dangling,
120 : .expected = symlnk_dangling,
121 : .attr = FILE_ATTRIBUTE_NORMAL,
122 : }, {
123 : .name = symlnk_in_share,
124 : .target = symlnk_dst_in_share,
125 : .expected = symlnk_in_share,
126 : .attr = FILE_ATTRIBUTE_NORMAL,
127 : }, {
128 : .name = symlnk_outside_share,
129 : .target = symlnk_dst_outside_share,
130 : .expected = symlnk_outside_share,
131 : .attr = FILE_ATTRIBUTE_NORMAL,
132 : }, {
133 : .name = NULL,
134 : }
135 : };
136 : int i;
137 0 : bool correct = false;
138 :
139 0 : frame = talloc_stackframe();
140 :
141 0 : printf("Starting POSIX-LS-WILDCARD test\n");
142 :
143 0 : if (!torture_open_connection(&cli_unix, 0)) {
144 0 : TALLOC_FREE(frame);
145 0 : return false;
146 : }
147 :
148 0 : if (!torture_open_connection(&cli_win, 0)) {
149 0 : TALLOC_FREE(frame);
150 0 : return false;
151 : }
152 :
153 0 : torture_conn_set_sockopt(cli_unix);
154 0 : torture_conn_set_sockopt(cli_win);
155 :
156 0 : status = torture_setup_unix_extensions(cli_unix);
157 0 : if (!NT_STATUS_IS_OK(status)) {
158 0 : TALLOC_FREE(frame);
159 0 : return false;
160 : }
161 :
162 0 : cli_posix_unlink(cli_unix, file);
163 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
164 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
165 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
166 :
167 0 : status = cli_posix_open(cli_unix,
168 : file,
169 : O_RDWR|O_CREAT,
170 : 0666,
171 : &fnum);
172 0 : if (!NT_STATUS_IS_OK(status)) {
173 0 : printf("cli_posix_open of %s failed error %s\n",
174 : file,
175 : nt_errstr(status));
176 0 : goto out;
177 : }
178 :
179 0 : status = cli_close(cli_unix, fnum);
180 0 : if (!NT_STATUS_IS_OK(status)) {
181 0 : printf("cli_close failed %s\n", nt_errstr(status));
182 0 : goto out;
183 : }
184 0 : fnum = (uint16_t)-1;
185 :
186 0 : for (i = 0; state[i].name != NULL; i++) {
187 0 : status = cli_posix_symlink(cli_unix,
188 : state[i].target,
189 : state[i].name);
190 0 : if (!NT_STATUS_IS_OK(status)) {
191 0 : printf("POSIX symlink of %s failed (%s)\n",
192 : symlnk_dangling, nt_errstr(status));
193 0 : goto out;
194 : }
195 : }
196 :
197 0 : printf("Doing Windows ls *\n");
198 :
199 0 : status = cli_list(cli_win, "*", 0, posix_ls_fn, state);
200 0 : if (!NT_STATUS_IS_OK(status)) {
201 0 : printf("cli_list failed %s\n", nt_errstr(status));
202 0 : goto out;
203 : }
204 :
205 0 : if (!posix_test_entry_check(state, symlnk_dangling, false, 0)) {
206 0 : goto out;
207 : }
208 0 : if (!posix_test_entry_check(state, symlnk_outside_share, false, 0)) {
209 0 : goto out;
210 : }
211 0 : if (!posix_test_entry_check(state, symlnk_in_share, true, 0)) {
212 0 : goto out;
213 : }
214 :
215 0 : posix_test_entries_reset(state);
216 :
217 0 : printf("Doing POSIX ls *\n");
218 :
219 0 : status = cli_list(cli_unix, "*", 0, posix_ls_fn, state);
220 0 : if (!NT_STATUS_IS_OK(status)) {
221 0 : printf("cli_close failed %s\n", nt_errstr(status));
222 0 : goto out;
223 : }
224 :
225 0 : if (!posix_test_entry_check(state,
226 : symlnk_dangling,
227 : true,
228 : strlen(symlnk_dst_dangling)))
229 : {
230 0 : goto out;
231 : }
232 0 : if (!posix_test_entry_check(state,
233 : symlnk_outside_share,
234 : true,
235 : strlen(symlnk_dst_outside_share)))
236 : {
237 0 : goto out;
238 : }
239 0 : if (!posix_test_entry_check(state,
240 : symlnk_in_share,
241 : true,
242 : strlen(symlnk_dst_in_share))) {
243 0 : goto out;
244 : }
245 :
246 0 : printf("POSIX-LS-WILDCARD test passed\n");
247 0 : correct = true;
248 :
249 0 : out:
250 0 : cli_posix_unlink(cli_unix, file);
251 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
252 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
253 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
254 :
255 0 : if (!torture_close_connection(cli_unix)) {
256 0 : correct = false;
257 : }
258 0 : if (!torture_close_connection(cli_win)) {
259 0 : correct = false;
260 : }
261 :
262 0 : TALLOC_FREE(frame);
263 0 : return correct;
264 : }
265 :
266 : /*
267 : Test non-POSIX vs POSIX ls single of symlinks
268 : */
269 0 : bool run_posix_ls_single_test(int dummy)
270 : {
271 0 : TALLOC_CTX *frame = NULL;
272 0 : struct cli_state *cli_unix = NULL;
273 0 : struct cli_state *cli_win = NULL;
274 0 : uint16_t fnum = (uint16_t)-1;
275 : NTSTATUS status;
276 0 : const char *file = "file";
277 0 : const char *symlnk_dangling = "dangling";
278 0 : const char *symlnk_dst_dangling = "xxxxxxx";
279 0 : const char *symlnk_in_share = "symlnk_in_share";
280 0 : const char *symlnk_dst_in_share = file;
281 0 : const char *symlnk_outside_share = "symlnk_outside_share";
282 0 : const char *symlnk_dst_outside_share = "/etc/passwd";
283 0 : struct posix_test_entry state[] = {
284 : {
285 : .name = symlnk_dangling,
286 : .target = symlnk_dst_dangling,
287 : .expected = symlnk_dangling,
288 : .attr = FILE_ATTRIBUTE_NORMAL,
289 : }, {
290 : .name = symlnk_in_share,
291 : .target = symlnk_dst_in_share,
292 : .expected = symlnk_in_share,
293 : .attr = FILE_ATTRIBUTE_NORMAL,
294 : }, {
295 : .name = symlnk_outside_share,
296 : .target = symlnk_dst_outside_share,
297 : .expected = symlnk_outside_share,
298 : .attr = FILE_ATTRIBUTE_NORMAL,
299 : }, {
300 : .name = NULL,
301 : }
302 : };
303 : int i;
304 0 : bool correct = false;
305 :
306 0 : frame = talloc_stackframe();
307 :
308 0 : printf("Starting POSIX-LS-SINGLE test\n");
309 :
310 0 : if (!torture_open_connection(&cli_unix, 0)) {
311 0 : TALLOC_FREE(frame);
312 0 : return false;
313 : }
314 :
315 0 : if (!torture_init_connection(&cli_win)) {
316 0 : TALLOC_FREE(frame);
317 0 : return false;
318 : }
319 :
320 0 : status = smbXcli_negprot(cli_win->conn,
321 0 : cli_win->timeout,
322 0 : lp_client_min_protocol(),
323 0 : lp_client_max_protocol());
324 0 : if (!NT_STATUS_IS_OK(status)) {
325 0 : printf("smbXcli_negprot returned %s\n", nt_errstr(status));
326 0 : TALLOC_FREE(frame);
327 0 : return false;
328 : }
329 :
330 0 : status = cli_session_setup_creds(cli_win, torture_creds);
331 0 : if (!NT_STATUS_IS_OK(status)) {
332 0 : printf("smb2cli_sesssetup returned %s\n", nt_errstr(status));
333 0 : TALLOC_FREE(frame);
334 0 : return false;
335 : }
336 :
337 0 : status = cli_tree_connect(cli_win, share, "?????", NULL);
338 0 : if (!NT_STATUS_IS_OK(status)) {
339 0 : printf("cli_tree_connect returned %s\n", nt_errstr(status));
340 0 : TALLOC_FREE(frame);
341 0 : return false;
342 : }
343 0 : torture_conn_set_sockopt(cli_unix);
344 0 : torture_conn_set_sockopt(cli_win);
345 :
346 0 : status = torture_setup_unix_extensions(cli_unix);
347 0 : if (!NT_STATUS_IS_OK(status)) {
348 0 : TALLOC_FREE(frame);
349 0 : return false;
350 : }
351 :
352 0 : cli_posix_unlink(cli_unix, file);
353 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
354 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
355 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
356 :
357 0 : status = cli_posix_open(cli_unix,
358 : file,
359 : O_RDWR|O_CREAT,
360 : 0666,
361 : &fnum);
362 0 : if (!NT_STATUS_IS_OK(status)) {
363 0 : printf("cli_posix_open of %s failed error %s\n",
364 : file,
365 : nt_errstr(status));
366 0 : goto out;
367 : }
368 :
369 0 : status = cli_close(cli_unix, fnum);
370 0 : if (!NT_STATUS_IS_OK(status)) {
371 0 : printf("cli_close failed %s\n", nt_errstr(status));
372 0 : goto out;
373 : }
374 0 : fnum = (uint16_t)-1;
375 :
376 0 : for (i = 0; state[i].name != NULL; i++) {
377 0 : status = cli_posix_symlink(cli_unix,
378 : state[i].target,
379 : state[i].name);
380 0 : if (!NT_STATUS_IS_OK(status)) {
381 0 : printf("POSIX symlink of %s failed (%s)\n",
382 : symlnk_dangling, nt_errstr(status));
383 0 : goto out;
384 : }
385 : }
386 :
387 0 : printf("Doing Windows ls single\n");
388 :
389 0 : cli_list(cli_win, symlnk_dangling, 0, posix_ls_fn, state);
390 0 : cli_list(cli_win, symlnk_outside_share, 0, posix_ls_fn, state);
391 0 : cli_list(cli_win, symlnk_in_share, 0, posix_ls_fn, state);
392 :
393 0 : if (!posix_test_entry_check(state, symlnk_dangling, false, 0)) {
394 0 : goto out;
395 : }
396 0 : if (!posix_test_entry_check(state, symlnk_outside_share, false, 0)) {
397 0 : goto out;
398 : }
399 0 : if (!posix_test_entry_check(state, symlnk_in_share, true, 0)) {
400 0 : goto out;
401 : }
402 :
403 0 : posix_test_entries_reset(state);
404 :
405 0 : printf("Doing POSIX ls single\n");
406 :
407 0 : cli_list(cli_unix, symlnk_dangling, 0, posix_ls_fn, state);
408 0 : cli_list(cli_unix, symlnk_outside_share, 0, posix_ls_fn, state);
409 0 : cli_list(cli_unix, symlnk_in_share, 0, posix_ls_fn, state);
410 :
411 0 : if (!posix_test_entry_check(state,
412 : symlnk_dangling,
413 : true,
414 : strlen(symlnk_dst_dangling)))
415 : {
416 0 : goto out;
417 : }
418 0 : if (!posix_test_entry_check(state,
419 : symlnk_outside_share,
420 : true,
421 : strlen(symlnk_dst_outside_share)))
422 : {
423 0 : goto out;
424 : }
425 0 : if (!posix_test_entry_check(state,
426 : symlnk_in_share,
427 : true,
428 : strlen(symlnk_dst_in_share))) {
429 0 : goto out;
430 : }
431 :
432 0 : printf("POSIX-LS-SINGLE test passed\n");
433 0 : correct = true;
434 :
435 0 : out:
436 0 : cli_posix_unlink(cli_unix, file);
437 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
438 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
439 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
440 :
441 0 : if (!torture_close_connection(cli_unix)) {
442 0 : correct = false;
443 : }
444 0 : if (!torture_close_connection(cli_win)) {
445 0 : correct = false;
446 : }
447 :
448 0 : TALLOC_FREE(frame);
449 0 : return correct;
450 : }
451 :
452 : /*
453 : Test POSIX readlink of symlinks
454 : */
455 0 : bool run_posix_readlink_test(int dummy)
456 : {
457 0 : TALLOC_CTX *frame = NULL;
458 0 : struct cli_state *cli_unix = NULL;
459 0 : uint16_t fnum = (uint16_t)-1;
460 : NTSTATUS status;
461 0 : const char *file = "file";
462 0 : const char *symlnk_dangling = "dangling";
463 0 : const char *symlnk_dst_dangling = "xxxxxxx";
464 0 : const char *symlnk_in_share = "symlnk_in_share";
465 0 : const char *symlnk_dst_in_share = file;
466 0 : const char *symlnk_outside_share = "symlnk_outside_share";
467 0 : const char *symlnk_dst_outside_share = "/etc/passwd";
468 0 : struct posix_test_entry state[] = {
469 : {
470 : .name = symlnk_dangling,
471 : .target = symlnk_dst_dangling,
472 : .expected = symlnk_dangling,
473 : .attr = FILE_ATTRIBUTE_NORMAL,
474 : }, {
475 : .name = symlnk_in_share,
476 : .target = symlnk_dst_in_share,
477 : .expected = symlnk_in_share,
478 : .attr = FILE_ATTRIBUTE_NORMAL,
479 : }, {
480 : .name = symlnk_outside_share,
481 : .target = symlnk_dst_outside_share,
482 : .expected = symlnk_outside_share,
483 : .attr = FILE_ATTRIBUTE_NORMAL,
484 : }, {
485 : .name = NULL,
486 : }
487 : };
488 : int i;
489 0 : bool correct = false;
490 :
491 0 : frame = talloc_stackframe();
492 :
493 0 : printf("Starting POSIX-READLINK test\n");
494 :
495 0 : if (!torture_open_connection(&cli_unix, 0)) {
496 0 : TALLOC_FREE(frame);
497 0 : return false;
498 : }
499 :
500 0 : torture_conn_set_sockopt(cli_unix);
501 :
502 0 : status = torture_setup_unix_extensions(cli_unix);
503 0 : if (!NT_STATUS_IS_OK(status)) {
504 0 : TALLOC_FREE(frame);
505 0 : return false;
506 : }
507 :
508 0 : cli_posix_unlink(cli_unix, file);
509 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
510 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
511 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
512 :
513 0 : status = cli_posix_open(cli_unix,
514 : file,
515 : O_RDWR|O_CREAT,
516 : 0666,
517 : &fnum);
518 0 : if (!NT_STATUS_IS_OK(status)) {
519 0 : printf("cli_posix_open of %s failed error %s\n",
520 : file,
521 : nt_errstr(status));
522 0 : goto out;
523 : }
524 :
525 0 : status = cli_close(cli_unix, fnum);
526 0 : if (!NT_STATUS_IS_OK(status)) {
527 0 : printf("cli_close failed %s\n", nt_errstr(status));
528 0 : goto out;
529 : }
530 0 : fnum = (uint16_t)-1;
531 :
532 0 : for (i = 0; state[i].name != NULL; i++) {
533 0 : status = cli_posix_symlink(cli_unix,
534 : state[i].target,
535 : state[i].name);
536 0 : if (!NT_STATUS_IS_OK(status)) {
537 0 : printf("POSIX symlink of %s failed (%s)\n",
538 : symlnk_dangling, nt_errstr(status));
539 0 : goto out;
540 : }
541 : }
542 :
543 0 : for (i = 0; state[i].name != NULL; i++) {
544 0 : char *target = NULL;
545 :
546 0 : status = cli_readlink(
547 : cli_unix,
548 : state[i].name,
549 : talloc_tos(),
550 : &target,
551 : NULL,
552 : NULL);
553 0 : if (!NT_STATUS_IS_OK(status)) {
554 0 : printf("POSIX readlink on %s failed (%s)\n",
555 : state[i].name, nt_errstr(status));
556 0 : goto out;
557 : }
558 0 : if (strequal(target, state[i].target)) {
559 0 : state[i].ok = true;
560 0 : state[i].returned_size = strlen(target);
561 : }
562 : }
563 :
564 0 : if (!posix_test_entry_check(state,
565 : symlnk_dangling,
566 : true,
567 : strlen(symlnk_dst_dangling)))
568 : {
569 0 : goto out;
570 : }
571 0 : if (!posix_test_entry_check(state,
572 : symlnk_outside_share,
573 : true,
574 : strlen(symlnk_dst_outside_share)))
575 : {
576 0 : goto out;
577 : }
578 0 : if (!posix_test_entry_check(state,
579 : symlnk_in_share,
580 : true,
581 : strlen(symlnk_dst_in_share))) {
582 0 : goto out;
583 : }
584 :
585 0 : printf("POSIX-READLINK test passed\n");
586 0 : correct = true;
587 :
588 0 : out:
589 0 : cli_posix_unlink(cli_unix, file);
590 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
591 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
592 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
593 :
594 0 : if (!torture_close_connection(cli_unix)) {
595 0 : correct = false;
596 : }
597 :
598 0 : TALLOC_FREE(frame);
599 0 : return correct;
600 : }
601 :
602 : /*
603 : Test POSIX stat of symlinks
604 : */
605 0 : bool run_posix_stat_test(int dummy)
606 : {
607 0 : TALLOC_CTX *frame = NULL;
608 0 : struct cli_state *cli_unix = NULL;
609 0 : uint16_t fnum = (uint16_t)-1;
610 : NTSTATUS status;
611 0 : const char *file = "file";
612 0 : const char *symlnk_dangling = "dangling";
613 0 : const char *symlnk_dst_dangling = "xxxxxxx";
614 0 : const char *symlnk_in_share = "symlnk_in_share";
615 0 : const char *symlnk_dst_in_share = file;
616 0 : const char *symlnk_outside_share = "symlnk_outside_share";
617 0 : const char *symlnk_dst_outside_share = "/etc/passwd";
618 0 : struct posix_test_entry state[] = {
619 : {
620 : .name = symlnk_dangling,
621 : .target = symlnk_dst_dangling,
622 : .expected = symlnk_dangling,
623 : }, {
624 : .name = symlnk_in_share,
625 : .target = symlnk_dst_in_share,
626 : .expected = symlnk_in_share,
627 : }, {
628 : .name = symlnk_outside_share,
629 : .target = symlnk_dst_outside_share,
630 : .expected = symlnk_outside_share,
631 : }, {
632 : .name = NULL,
633 : }
634 : };
635 : int i;
636 0 : bool correct = false;
637 :
638 0 : frame = talloc_stackframe();
639 :
640 0 : printf("Starting POSIX-STAT test\n");
641 :
642 0 : if (!torture_open_connection(&cli_unix, 0)) {
643 0 : TALLOC_FREE(frame);
644 0 : return false;
645 : }
646 :
647 0 : torture_conn_set_sockopt(cli_unix);
648 :
649 0 : status = torture_setup_unix_extensions(cli_unix);
650 0 : if (!NT_STATUS_IS_OK(status)) {
651 0 : TALLOC_FREE(frame);
652 0 : return false;
653 : }
654 :
655 0 : cli_posix_unlink(cli_unix, file);
656 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
657 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
658 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
659 :
660 0 : status = cli_posix_open(cli_unix,
661 : file,
662 : O_RDWR|O_CREAT,
663 : 0666,
664 : &fnum);
665 0 : if (!NT_STATUS_IS_OK(status)) {
666 0 : printf("cli_posix_open of %s failed error %s\n",
667 : file,
668 : nt_errstr(status));
669 0 : goto out;
670 : }
671 :
672 0 : status = cli_close(cli_unix, fnum);
673 0 : if (!NT_STATUS_IS_OK(status)) {
674 0 : printf("cli_close failed %s\n", nt_errstr(status));
675 0 : goto out;
676 : }
677 0 : fnum = (uint16_t)-1;
678 :
679 0 : for (i = 0; state[i].name != NULL; i++) {
680 0 : status = cli_posix_symlink(cli_unix,
681 : state[i].target,
682 : state[i].name);
683 0 : if (!NT_STATUS_IS_OK(status)) {
684 0 : printf("POSIX symlink of %s failed (%s)\n",
685 : symlnk_dangling, nt_errstr(status));
686 0 : goto out;
687 : }
688 : }
689 :
690 0 : for (i = 0; state[i].name != NULL; i++) {
691 : SMB_STRUCT_STAT sbuf;
692 :
693 0 : status = cli_posix_stat(cli_unix,
694 : state[i].name,
695 : &sbuf);
696 0 : if (!NT_STATUS_IS_OK(status)) {
697 0 : printf("POSIX stat on %s failed (%s)\n",
698 : state[i].name, nt_errstr(status));
699 0 : continue;
700 : }
701 0 : state[i].ok = true;
702 0 : state[i].returned_size = sbuf.st_ex_size;
703 : }
704 :
705 0 : if (!posix_test_entry_check(state,
706 : symlnk_dangling,
707 : true,
708 : strlen(symlnk_dst_dangling)))
709 : {
710 0 : goto out;
711 : }
712 0 : if (!posix_test_entry_check(state,
713 : symlnk_outside_share,
714 : true,
715 : strlen(symlnk_dst_outside_share)))
716 : {
717 0 : goto out;
718 : }
719 0 : if (!posix_test_entry_check(state,
720 : symlnk_in_share,
721 : true,
722 : strlen(symlnk_dst_in_share))) {
723 0 : goto out;
724 : }
725 :
726 0 : printf("POSIX-STAT test passed\n");
727 0 : correct = true;
728 :
729 0 : out:
730 0 : cli_posix_unlink(cli_unix, file);
731 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
732 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
733 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
734 :
735 0 : if (!torture_close_connection(cli_unix)) {
736 0 : correct = false;
737 : }
738 :
739 0 : TALLOC_FREE(frame);
740 0 : return correct;
741 : }
742 :
743 : /*
744 : Test Creating files and directories directly
745 : under a symlink.
746 : */
747 0 : bool run_posix_symlink_parent_test(int dummy)
748 : {
749 0 : TALLOC_CTX *frame = NULL;
750 0 : struct cli_state *cli_unix = NULL;
751 0 : uint16_t fnum = (uint16_t)-1;
752 : NTSTATUS status;
753 0 : const char *parent_dir = "target_dir";
754 0 : const char *parent_symlink = "symlink_to_target_dir";
755 0 : const char *fname_real = "target_dir/file";
756 0 : const char *dname_real = "target_dir/dir";
757 0 : const char *fname_link = "symlink_to_target_dir/file";
758 0 : const char *dname_link = "symlink_to_target_dir/dir";
759 0 : const char *sname_link = "symlink_to_target_dir/symlink";
760 0 : const char *hname_link = "symlink_to_target_dir/hardlink";
761 0 : bool correct = false;
762 :
763 0 : frame = talloc_stackframe();
764 :
765 0 : printf("Starting POSIX-SYMLINK-PARENT test\n");
766 :
767 0 : if (!torture_open_connection(&cli_unix, 0)) {
768 0 : TALLOC_FREE(frame);
769 0 : return false;
770 : }
771 :
772 0 : torture_conn_set_sockopt(cli_unix);
773 :
774 0 : status = torture_setup_unix_extensions(cli_unix);
775 0 : if (!NT_STATUS_IS_OK(status)) {
776 0 : TALLOC_FREE(frame);
777 0 : return false;
778 : }
779 :
780 : /* Start with a clean slate. */
781 0 : cli_posix_unlink(cli_unix, fname_real);
782 0 : cli_posix_rmdir(cli_unix, dname_real);
783 0 : cli_posix_unlink(cli_unix, fname_link);
784 0 : cli_posix_rmdir(cli_unix, dname_link);
785 0 : cli_posix_unlink(cli_unix, sname_link);
786 0 : cli_posix_unlink(cli_unix, hname_link);
787 0 : cli_posix_unlink(cli_unix, parent_symlink);
788 0 : cli_posix_rmdir(cli_unix, parent_dir);
789 :
790 : /* Create parent_dir. */
791 0 : status = cli_posix_mkdir(cli_unix, parent_dir, 0777);
792 0 : if (!NT_STATUS_IS_OK(status)) {
793 0 : printf("cli_posix_mkdir of %s failed error %s\n",
794 : parent_dir,
795 : nt_errstr(status));
796 0 : goto out;
797 : }
798 : /* Create symlink to parent_dir. */
799 0 : status = cli_posix_symlink(cli_unix,
800 : parent_dir,
801 : parent_symlink);
802 0 : if (!NT_STATUS_IS_OK(status)) {
803 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
804 : parent_symlink,
805 : parent_dir,
806 : nt_errstr(status));
807 0 : goto out;
808 : }
809 : /* Try and create a directory under the symlink. */
810 0 : status = cli_posix_mkdir(cli_unix, dname_link, 0777);
811 0 : if (!NT_STATUS_IS_OK(status)) {
812 0 : printf("cli_posix_mkdir of %s failed error %s\n",
813 : dname_link,
814 : nt_errstr(status));
815 0 : goto out;
816 : }
817 : /* Try and create a file under the symlink. */
818 0 : status = cli_posix_open(cli_unix,
819 : fname_link,
820 : O_RDWR|O_CREAT,
821 : 0666,
822 : &fnum);
823 0 : if (!NT_STATUS_IS_OK(status)) {
824 0 : printf("cli_posix_open of %s failed error %s\n",
825 : fname_link,
826 : nt_errstr(status));
827 0 : goto out;
828 : }
829 0 : status = cli_close(cli_unix, fnum);
830 0 : if (!NT_STATUS_IS_OK(status)) {
831 0 : printf("cli_close failed %s\n", nt_errstr(status));
832 0 : goto out;
833 : }
834 0 : fnum = (uint16_t)-1;
835 :
836 : /* Try and create a symlink to the file under the symlink. */
837 0 : status = cli_posix_symlink(cli_unix,
838 : fname_link,
839 : sname_link);
840 0 : if (!NT_STATUS_IS_OK(status)) {
841 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
842 : sname_link,
843 : fname_link,
844 : nt_errstr(status));
845 0 : goto out;
846 : }
847 :
848 : /* Try and create a hardlink to the file under the symlink. */
849 0 : status = cli_posix_hardlink(cli_unix,
850 : fname_link,
851 : hname_link);
852 0 : if (!NT_STATUS_IS_OK(status)) {
853 0 : printf("cli_posix_hardlink of %s -> %s failed error %s\n",
854 : hname_link,
855 : fname_link,
856 : nt_errstr(status));
857 0 : goto out;
858 : }
859 :
860 : /* Ensure we can delete the symlink via the parent symlink */
861 0 : status = cli_posix_unlink(cli_unix, sname_link);
862 0 : if (!NT_STATUS_IS_OK(status)) {
863 0 : printf("cli_posix_unlink of %s failed error %s\n",
864 : sname_link,
865 : nt_errstr(status));
866 0 : goto out;
867 : }
868 :
869 : /* Ensure we can delete the hardlink via the parent symlink */
870 0 : status = cli_posix_unlink(cli_unix, hname_link);
871 0 : if (!NT_STATUS_IS_OK(status)) {
872 0 : printf("cli_posix_unlink of %s failed error %s\n",
873 : hname_link,
874 : nt_errstr(status));
875 0 : goto out;
876 : }
877 :
878 : /* Ensure we can delete the directory via the parent symlink */
879 0 : status = cli_posix_rmdir(cli_unix, dname_link);
880 0 : if (!NT_STATUS_IS_OK(status)) {
881 0 : printf("cli_posix_rmdir of %s failed error %s\n",
882 : dname_link,
883 : nt_errstr(status));
884 0 : goto out;
885 : }
886 : /* Ensure we can delete the file via the parent symlink */
887 0 : status = cli_posix_unlink(cli_unix, fname_link);
888 0 : if (!NT_STATUS_IS_OK(status)) {
889 0 : printf("cli_posix_unlink of %s failed error %s\n",
890 : fname_link,
891 : nt_errstr(status));
892 0 : goto out;
893 : }
894 :
895 0 : printf("POSIX-SYMLINK-PARENT test passed\n");
896 0 : correct = true;
897 :
898 0 : out:
899 0 : if (fnum != (uint16_t)-1) {
900 0 : cli_close(cli_unix, fnum);
901 : }
902 0 : cli_posix_unlink(cli_unix, fname_real);
903 0 : cli_posix_rmdir(cli_unix, dname_real);
904 0 : cli_posix_unlink(cli_unix, fname_link);
905 0 : cli_posix_rmdir(cli_unix, dname_link);
906 0 : cli_posix_unlink(cli_unix, sname_link);
907 0 : cli_posix_unlink(cli_unix, hname_link);
908 0 : cli_posix_unlink(cli_unix, parent_symlink);
909 0 : cli_posix_rmdir(cli_unix, parent_dir);
910 :
911 0 : if (!torture_close_connection(cli_unix)) {
912 0 : correct = false;
913 : }
914 :
915 0 : TALLOC_FREE(frame);
916 0 : return correct;
917 : }
918 :
919 : /*
920 : Ensure we get an error when doing chmod on a symlink,
921 : whether it is pointing to a real object or dangling.
922 : */
923 0 : bool run_posix_symlink_chmod_test(int dummy)
924 : {
925 0 : TALLOC_CTX *frame = NULL;
926 0 : struct cli_state *cli_unix = NULL;
927 : NTSTATUS status;
928 0 : uint16_t fnum = (uint16_t)-1;
929 0 : const char *fname_real = "file_real";
930 0 : const char *fname_real_symlink = "file_real_symlink";
931 0 : const char *nonexist = "nonexist";
932 0 : const char *nonexist_symlink = "dangling_symlink";
933 0 : bool correct = false;
934 :
935 0 : frame = talloc_stackframe();
936 :
937 0 : printf("Starting POSIX-SYMLINK-CHMOD test\n");
938 :
939 0 : if (!torture_open_connection(&cli_unix, 0)) {
940 0 : TALLOC_FREE(frame);
941 0 : return false;
942 : }
943 :
944 0 : torture_conn_set_sockopt(cli_unix);
945 :
946 0 : status = torture_setup_unix_extensions(cli_unix);
947 0 : if (!NT_STATUS_IS_OK(status)) {
948 0 : TALLOC_FREE(frame);
949 0 : return false;
950 : }
951 :
952 : /* Start with a clean slate. */
953 0 : cli_posix_unlink(cli_unix, fname_real);
954 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
955 0 : cli_posix_unlink(cli_unix, nonexist);
956 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
957 :
958 : /* Create a real file. */
959 0 : status = cli_posix_open(cli_unix,
960 : fname_real,
961 : O_RDWR|O_CREAT,
962 : 0644,
963 : &fnum);
964 0 : if (!NT_STATUS_IS_OK(status)) {
965 0 : printf("cli_posix_open of %s failed error %s\n",
966 : fname_real,
967 : nt_errstr(status));
968 0 : goto out;
969 : }
970 0 : status = cli_close(cli_unix, fnum);
971 0 : if (!NT_STATUS_IS_OK(status)) {
972 0 : printf("cli_close failed %s\n", nt_errstr(status));
973 0 : goto out;
974 : }
975 0 : fnum = (uint16_t)-1;
976 :
977 : /* Create symlink to real target. */
978 0 : status = cli_posix_symlink(cli_unix,
979 : fname_real,
980 : fname_real_symlink);
981 0 : if (!NT_STATUS_IS_OK(status)) {
982 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
983 : fname_real_symlink,
984 : fname_real,
985 : nt_errstr(status));
986 0 : goto out;
987 : }
988 :
989 : /* We should not be able to chmod symlinks that point to something. */
990 0 : status = cli_posix_chmod(cli_unix, fname_real_symlink, 0777);
991 :
992 : /* This should fail with something other than server crashed. */
993 0 : if (NT_STATUS_IS_OK(status)) {
994 0 : printf("cli_posix_chmod of %s succeeded (should have failed)\n",
995 : fname_real_symlink);
996 0 : goto out;
997 : }
998 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED)) {
999 : /* Oops. Server crashed. */
1000 0 : printf("cli_posix_chmod of %s failed error %s\n",
1001 : fname_real_symlink,
1002 : nt_errstr(status));
1003 0 : goto out;
1004 : }
1005 : /* Any other failure is ok. */
1006 :
1007 : /* Now create symlink to non-existing target. */
1008 0 : status = cli_posix_symlink(cli_unix,
1009 : nonexist,
1010 : nonexist_symlink);
1011 0 : if (!NT_STATUS_IS_OK(status)) {
1012 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1013 : nonexist_symlink,
1014 : nonexist,
1015 : nt_errstr(status));
1016 0 : goto out;
1017 : }
1018 :
1019 : /* We should not be able to chmod symlinks that point to nothing. */
1020 0 : status = cli_posix_chmod(cli_unix, nonexist_symlink, 0777);
1021 :
1022 : /* This should fail with something other than server crashed. */
1023 0 : if (NT_STATUS_IS_OK(status)) {
1024 0 : printf("cli_posix_chmod of %s succeeded (should have failed)\n",
1025 : nonexist_symlink);
1026 0 : goto out;
1027 : }
1028 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED)) {
1029 : /* Oops. Server crashed. */
1030 0 : printf("cli_posix_chmod of %s failed error %s\n",
1031 : nonexist_symlink,
1032 : nt_errstr(status));
1033 0 : goto out;
1034 : }
1035 :
1036 : /* Any other failure is ok. */
1037 0 : printf("POSIX-SYMLINK-CHMOD test passed (expected failure was %s)\n",
1038 : nt_errstr(status));
1039 0 : correct = true;
1040 :
1041 0 : out:
1042 0 : if (fnum != (uint16_t)-1) {
1043 0 : cli_close(cli_unix, fnum);
1044 : }
1045 0 : cli_posix_unlink(cli_unix, fname_real);
1046 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1047 0 : cli_posix_unlink(cli_unix, nonexist);
1048 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1049 :
1050 0 : if (!torture_close_connection(cli_unix)) {
1051 0 : correct = false;
1052 : }
1053 :
1054 0 : TALLOC_FREE(frame);
1055 0 : return correct;
1056 : }
1057 :
1058 : /*
1059 : Ensure we get an ACL containing OI|IO ACE entries
1060 : after we add a default POSIX ACL to a directory.
1061 : This will only ever be an SMB1 test as it depends
1062 : on POSIX ACL semantics.
1063 : */
1064 0 : bool run_posix_dir_default_acl_test(int dummy)
1065 : {
1066 0 : TALLOC_CTX *frame = NULL;
1067 0 : struct cli_state *cli_unix = NULL;
1068 : NTSTATUS status;
1069 0 : uint16_t fnum = (uint16_t)-1;
1070 0 : const char *dname = "dir_with_default_acl";
1071 0 : bool correct = false;
1072 : SMB_STRUCT_STAT sbuf;
1073 0 : size_t acl_size = 0;
1074 0 : char *aclbuf = NULL;
1075 0 : size_t num_file_acls = 0;
1076 0 : size_t num_dir_acls = 0;
1077 : size_t expected_buflen;
1078 0 : uint8_t def_acl[SMB_POSIX_ACL_HEADER_SIZE +
1079 : 5*SMB_POSIX_ACL_ENTRY_SIZE] = {0};
1080 0 : uint8_t *p = NULL;
1081 0 : uint32_t i = 0;
1082 0 : struct security_descriptor *sd = NULL;
1083 0 : bool got_inherit = false;
1084 :
1085 0 : frame = talloc_stackframe();
1086 :
1087 0 : printf("Starting POSIX-DIR-DEFAULT-ACL test\n");
1088 :
1089 0 : if (!torture_open_connection(&cli_unix, 0)) {
1090 0 : TALLOC_FREE(frame);
1091 0 : return false;
1092 : }
1093 :
1094 0 : torture_conn_set_sockopt(cli_unix);
1095 :
1096 0 : status = torture_setup_unix_extensions(cli_unix);
1097 0 : if (!NT_STATUS_IS_OK(status)) {
1098 0 : TALLOC_FREE(frame);
1099 0 : return false;
1100 : }
1101 :
1102 : /* Start with a clean slate. */
1103 0 : cli_posix_unlink(cli_unix, dname);
1104 0 : cli_posix_rmdir(cli_unix, dname);
1105 :
1106 0 : status = cli_posix_mkdir(cli_unix, dname, 0777);
1107 0 : if (!NT_STATUS_IS_OK(status)) {
1108 0 : printf("cli_posix_mkdir of %s failed error %s\n",
1109 : dname,
1110 : nt_errstr(status));
1111 0 : goto out;
1112 : }
1113 :
1114 : /* Do a posix stat to get the owner. */
1115 0 : status = cli_posix_stat(cli_unix, dname, &sbuf);
1116 0 : if (!NT_STATUS_IS_OK(status)) {
1117 0 : printf("cli_posix_stat of %s failed %s\n",
1118 : dname,
1119 : nt_errstr(status));
1120 0 : goto out;
1121 : }
1122 :
1123 : /* Get the ACL on the directory. */
1124 0 : status = cli_posix_getacl(cli_unix, dname, frame, &acl_size, &aclbuf);
1125 0 : if (!NT_STATUS_IS_OK(status)) {
1126 0 : printf("cli_posix_getacl on %s failed %s\n",
1127 : dname,
1128 : nt_errstr(status));
1129 0 : goto out;
1130 : }
1131 :
1132 0 : if (acl_size < 6 || SVAL(aclbuf,0) != SMB_POSIX_ACL_VERSION) {
1133 0 : printf("%s, unknown POSIX acl version %u.\n",
1134 : dname,
1135 0 : (unsigned int)CVAL(aclbuf,0) );
1136 0 : goto out;
1137 : }
1138 :
1139 0 : num_file_acls = SVAL(aclbuf,2);
1140 0 : num_dir_acls = SVAL(aclbuf,4);
1141 :
1142 : /*
1143 : * No overflow check, num_*_acls comes from a 16-bit value,
1144 : * and we expect expected_buflen (size_t) to be of at least 32
1145 : * bit.
1146 : */
1147 0 : expected_buflen = SMB_POSIX_ACL_HEADER_SIZE +
1148 0 : SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls);
1149 :
1150 0 : if (acl_size != expected_buflen) {
1151 0 : printf("%s, incorrect POSIX acl buffer size "
1152 : "(should be %zu, was %zu).\n",
1153 : dname,
1154 : expected_buflen,
1155 : acl_size);
1156 0 : goto out;
1157 : }
1158 :
1159 0 : if (num_dir_acls != 0) {
1160 0 : printf("%s, POSIX default acl already exists"
1161 : "(should be 0, was %zu).\n",
1162 : dname,
1163 : num_dir_acls);
1164 0 : goto out;
1165 : }
1166 :
1167 : /*
1168 : * Get the Windows ACL on the directory.
1169 : * Make sure there are no inheritable entries.
1170 : */
1171 0 : status = cli_ntcreate(cli_unix,
1172 : dname,
1173 : 0,
1174 : SEC_STD_READ_CONTROL,
1175 : 0,
1176 : FILE_SHARE_READ|
1177 : FILE_SHARE_WRITE|
1178 : FILE_SHARE_DELETE,
1179 : FILE_OPEN,
1180 : FILE_DIRECTORY_FILE,
1181 : 0x0,
1182 : &fnum,
1183 : NULL);
1184 0 : if (!NT_STATUS_IS_OK(status)) {
1185 0 : printf("Failed to open directory %s: %s\n",
1186 : dname,
1187 : nt_errstr(status));
1188 0 : goto out;
1189 : }
1190 :
1191 0 : status = cli_query_security_descriptor(cli_unix,
1192 : fnum,
1193 : SECINFO_DACL,
1194 : frame,
1195 : &sd);
1196 0 : if (!NT_STATUS_IS_OK(status)) {
1197 0 : printf("Failed to get security descriptor on directory %s: %s\n",
1198 : dname,
1199 : nt_errstr(status));
1200 0 : goto out;
1201 : }
1202 :
1203 0 : for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1204 0 : struct security_ace *ace = &sd->dacl->aces[i];
1205 0 : if (ace->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
1206 : SEC_ACE_FLAG_CONTAINER_INHERIT)) {
1207 0 : printf("security descritor on directory %s already "
1208 : "contains inheritance flags\n",
1209 : dname);
1210 0 : sec_desc_print(NULL, stdout, sd, true);
1211 0 : goto out;
1212 : }
1213 : }
1214 :
1215 0 : TALLOC_FREE(sd);
1216 :
1217 : /* Construct a new default ACL. */
1218 0 : SSVAL(def_acl,0,SMB_POSIX_ACL_VERSION);
1219 0 : SSVAL(def_acl,2,SMB_POSIX_IGNORE_ACE_ENTRIES);
1220 0 : SSVAL(def_acl,4,5); /* num_dir_acls. */
1221 :
1222 0 : p = def_acl + SMB_POSIX_ACL_HEADER_SIZE;
1223 :
1224 : /* USER_OBJ. */
1225 0 : SCVAL(p,0,SMB_POSIX_ACL_USER_OBJ); /* tagtype. */
1226 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1227 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1228 :
1229 : /* GROUP_OBJ. */
1230 0 : SCVAL(p,0,SMB_POSIX_ACL_GROUP_OBJ); /* tagtype. */
1231 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1232 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1233 :
1234 : /* OTHER. */
1235 0 : SCVAL(p,0,SMB_POSIX_ACL_OTHER); /* tagtype. */
1236 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1237 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1238 :
1239 : /* Explicit user. */
1240 0 : SCVAL(p,0,SMB_POSIX_ACL_USER); /* tagtype. */
1241 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1242 0 : SIVAL(p,2,sbuf.st_ex_uid);
1243 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1244 :
1245 : /* MASK. */
1246 0 : SCVAL(p,0,SMB_POSIX_ACL_MASK); /* tagtype. */
1247 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1248 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1249 :
1250 : /* Set the POSIX default ACL. */
1251 0 : status = cli_posix_setacl(cli_unix, dname, def_acl, sizeof(def_acl));
1252 0 : if (!NT_STATUS_IS_OK(status)) {
1253 0 : printf("cli_posix_setacl on %s failed %s\n",
1254 : dname,
1255 : nt_errstr(status));
1256 0 : goto out;
1257 : }
1258 :
1259 : /*
1260 : * Get the Windows ACL on the directory again.
1261 : * Now there should be inheritable entries.
1262 : */
1263 :
1264 0 : status = cli_query_security_descriptor(cli_unix,
1265 : fnum,
1266 : SECINFO_DACL,
1267 : frame,
1268 : &sd);
1269 0 : if (!NT_STATUS_IS_OK(status)) {
1270 0 : printf("Failed (2) to get security descriptor "
1271 : "on directory %s: %s\n",
1272 : dname,
1273 : nt_errstr(status));
1274 0 : goto out;
1275 : }
1276 :
1277 0 : for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1278 0 : struct security_ace *ace = &sd->dacl->aces[i];
1279 0 : if (ace->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
1280 : SEC_ACE_FLAG_CONTAINER_INHERIT)) {
1281 0 : got_inherit = true;
1282 0 : break;
1283 : }
1284 : }
1285 :
1286 0 : if (!got_inherit) {
1287 0 : printf("security descritor on directory %s does not "
1288 : "contain inheritance flags\n",
1289 : dname);
1290 0 : sec_desc_print(NULL, stdout, sd, true);
1291 0 : goto out;
1292 : }
1293 :
1294 0 : cli_close(cli_unix, fnum);
1295 0 : fnum = (uint16_t)-1;
1296 0 : printf("POSIX-DIR-DEFAULT-ACL test passed\n");
1297 0 : correct = true;
1298 :
1299 0 : out:
1300 :
1301 0 : TALLOC_FREE(sd);
1302 :
1303 0 : if (fnum != (uint16_t)-1) {
1304 0 : cli_close(cli_unix, fnum);
1305 : }
1306 0 : cli_posix_unlink(cli_unix, dname);
1307 0 : cli_posix_rmdir(cli_unix, dname);
1308 :
1309 0 : if (!torture_close_connection(cli_unix)) {
1310 0 : correct = false;
1311 : }
1312 :
1313 0 : TALLOC_FREE(frame);
1314 0 : return correct;
1315 : }
1316 :
1317 : /*
1318 : Ensure we can rename a symlink whether it is
1319 : pointing to a real object or dangling.
1320 : */
1321 0 : bool run_posix_symlink_rename_test(int dummy)
1322 : {
1323 0 : TALLOC_CTX *frame = NULL;
1324 0 : struct cli_state *cli_unix = NULL;
1325 : NTSTATUS status;
1326 0 : uint16_t fnum = (uint16_t)-1;
1327 0 : const char *fname_real = "file_real";
1328 0 : const char *fname_real_symlink = "file_real_symlink";
1329 0 : const char *fname_real_symlink_newname = "rename_file_real_symlink";
1330 0 : const char *nonexist = "nonexist";
1331 0 : const char *nonexist_symlink = "dangling_symlink";
1332 0 : const char *nonexist_symlink_newname = "dangling_symlink_rename";
1333 0 : bool correct = false;
1334 :
1335 0 : frame = talloc_stackframe();
1336 :
1337 0 : printf("Starting POSIX-SYMLINK-RENAME test\n");
1338 :
1339 0 : if (!torture_open_connection(&cli_unix, 0)) {
1340 0 : TALLOC_FREE(frame);
1341 0 : return false;
1342 : }
1343 :
1344 0 : torture_conn_set_sockopt(cli_unix);
1345 :
1346 0 : status = torture_setup_unix_extensions(cli_unix);
1347 0 : if (!NT_STATUS_IS_OK(status)) {
1348 0 : TALLOC_FREE(frame);
1349 0 : return false;
1350 : }
1351 :
1352 : /* Start with a clean slate. */
1353 0 : cli_posix_unlink(cli_unix, fname_real);
1354 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1355 0 : cli_posix_unlink(cli_unix, fname_real_symlink_newname);
1356 0 : cli_posix_unlink(cli_unix, nonexist);
1357 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1358 0 : cli_posix_unlink(cli_unix, nonexist_symlink_newname);
1359 :
1360 : /* Create a real file. */
1361 0 : status = cli_posix_open(cli_unix,
1362 : fname_real,
1363 : O_RDWR|O_CREAT,
1364 : 0644,
1365 : &fnum);
1366 0 : if (!NT_STATUS_IS_OK(status)) {
1367 0 : printf("cli_posix_open of %s failed error %s\n",
1368 : fname_real,
1369 : nt_errstr(status));
1370 0 : goto out;
1371 : }
1372 0 : status = cli_close(cli_unix, fnum);
1373 0 : if (!NT_STATUS_IS_OK(status)) {
1374 0 : printf("cli_close failed %s\n", nt_errstr(status));
1375 0 : goto out;
1376 : }
1377 0 : fnum = (uint16_t)-1;
1378 :
1379 : /* Create symlink to real target. */
1380 0 : status = cli_posix_symlink(cli_unix,
1381 : fname_real,
1382 : fname_real_symlink);
1383 0 : if (!NT_STATUS_IS_OK(status)) {
1384 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1385 : fname_real_symlink,
1386 : fname_real,
1387 : nt_errstr(status));
1388 0 : goto out;
1389 : }
1390 :
1391 : /* Ensure we can rename the symlink to the real file. */
1392 0 : status = cli_rename(cli_unix,
1393 : fname_real_symlink,
1394 : fname_real_symlink_newname,
1395 : false);
1396 0 : if (!NT_STATUS_IS_OK(status)) {
1397 0 : printf("cli_rename of %s -> %s failed %s\n",
1398 : fname_real_symlink,
1399 : fname_real_symlink_newname,
1400 : nt_errstr(status));
1401 0 : goto out;
1402 : }
1403 :
1404 : /* Now create symlink to non-existing target. */
1405 0 : status = cli_posix_symlink(cli_unix,
1406 : nonexist,
1407 : nonexist_symlink);
1408 0 : if (!NT_STATUS_IS_OK(status)) {
1409 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1410 : nonexist_symlink,
1411 : nonexist,
1412 : nt_errstr(status));
1413 0 : goto out;
1414 : }
1415 :
1416 : /* Ensure we can rename the dangling symlink. */
1417 0 : status = cli_rename(cli_unix,
1418 : nonexist_symlink,
1419 : nonexist_symlink_newname,
1420 : false);
1421 0 : if (!NT_STATUS_IS_OK(status)) {
1422 0 : printf("cli_rename of %s -> %s failed %s\n",
1423 : nonexist_symlink,
1424 : nonexist_symlink_newname,
1425 : nt_errstr(status));
1426 0 : goto out;
1427 : }
1428 :
1429 0 : printf("POSIX-SYMLINK-RENAME test passed\n");
1430 0 : correct = true;
1431 :
1432 0 : out:
1433 0 : if (fnum != (uint16_t)-1) {
1434 0 : cli_close(cli_unix, fnum);
1435 : }
1436 0 : cli_posix_unlink(cli_unix, fname_real);
1437 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1438 0 : cli_posix_unlink(cli_unix, fname_real_symlink_newname);
1439 0 : cli_posix_unlink(cli_unix, nonexist);
1440 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1441 0 : cli_posix_unlink(cli_unix, nonexist_symlink_newname);
1442 :
1443 0 : if (!torture_close_connection(cli_unix)) {
1444 0 : correct = false;
1445 : }
1446 :
1447 0 : TALLOC_FREE(frame);
1448 0 : return correct;
1449 : }
1450 :
1451 : /* List of info levels to try with a POSIX symlink path. */
1452 :
1453 : static struct {
1454 : uint32_t level;
1455 : const char *name;
1456 : } posix_smb1_qpath_array[] = {
1457 : { SMB_INFO_STANDARD, "SMB_INFO_STANDARD"},
1458 : { SMB_INFO_QUERY_EA_SIZE, "SMB_INFO_QUERY_EA_SIZE"},
1459 : { SMB_INFO_IS_NAME_VALID, "SMB_INFO_IS_NAME_VALID"},
1460 : { SMB_INFO_QUERY_EAS_FROM_LIST, "SMB_INFO_QUERY_EAS_FROM_LIST"},
1461 : { SMB_INFO_QUERY_ALL_EAS, "SMB_INFO_QUERY_ALL_EAS"},
1462 : { SMB_FILE_BASIC_INFORMATION, "SMB_FILE_BASIC_INFORMATION"},
1463 : { SMB_FILE_STANDARD_INFORMATION, "SMB_FILE_STANDARD_INFORMATION"},
1464 : { SMB_FILE_EA_INFORMATION, "SMB_FILE_EA_INFORMATION"},
1465 : { SMB_FILE_ALTERNATE_NAME_INFORMATION,"SMB_FILE_ALTERNATE_NAME_INFORMATION"},
1466 : { SMB_QUERY_FILE_NAME_INFO, "SMB_QUERY_FILE_NAME_INFO"},
1467 : { SMB_FILE_NORMALIZED_NAME_INFORMATION,"SMB_FILE_NORMALIZED_NAME_INFORMATION"},
1468 : { SMB_FILE_ALLOCATION_INFORMATION, "SMB_FILE_ALLOCATION_INFORMATION"},
1469 : { SMB_FILE_END_OF_FILE_INFORMATION, "SMB_FILE_END_OF_FILE_INFORMATION"},
1470 : { SMB_FILE_ALL_INFORMATION, "SMB_FILE_ALL_INFORMATION"},
1471 : { SMB_FILE_INTERNAL_INFORMATION, "SMB_FILE_INTERNAL_INFORMATION"},
1472 : { SMB_FILE_ACCESS_INFORMATION, "SMB_FILE_ACCESS_INFORMATION"},
1473 : { SMB_FILE_NAME_INFORMATION, "SMB_FILE_NAME_INFORMATION"},
1474 : { SMB_FILE_DISPOSITION_INFORMATION, "SMB_FILE_DISPOSITION_INFORMATION"},
1475 : { SMB_FILE_POSITION_INFORMATION, "SMB_FILE_POSITION_INFORMATION"},
1476 : { SMB_FILE_MODE_INFORMATION, "SMB_FILE_MODE_INFORMATION"},
1477 : { SMB_FILE_ALIGNMENT_INFORMATION, "SMB_FILE_ALIGNMENT_INFORMATION"},
1478 : { SMB_FILE_STREAM_INFORMATION, "SMB_FILE_STREAM_INFORMATION"},
1479 : { SMB_FILE_COMPRESSION_INFORMATION, "SMB_FILE_COMPRESSION_INFORMATION"},
1480 : { SMB_FILE_NETWORK_OPEN_INFORMATION, "SMB_FILE_NETWORK_OPEN_INFORMATION"},
1481 : { SMB_FILE_ATTRIBUTE_TAG_INFORMATION, "SMB_FILE_ATTRIBUTE_TAG_INFORMATION"},
1482 : { SMB_QUERY_FILE_UNIX_BASIC, "SMB_QUERY_FILE_UNIX_BASIC"},
1483 : { SMB_QUERY_FILE_UNIX_INFO2, "SMB_QUERY_FILE_UNIX_INFO2"},
1484 : { SMB_QUERY_FILE_UNIX_LINK, "SMB_QUERY_FILE_UNIX_LINK"},
1485 : { SMB_QUERY_POSIX_ACL, "SMB_QUERY_POSIX_ACL"},
1486 : { SMB_QUERY_POSIX_LOCK, "SMB_QUERY_POSIX_LOCK"},
1487 : };
1488 :
1489 0 : static NTSTATUS do_qpath(TALLOC_CTX *ctx,
1490 : struct cli_state *cli_unix,
1491 : const char *fname,
1492 : size_t i)
1493 : {
1494 : NTSTATUS status;
1495 :
1496 0 : if (posix_smb1_qpath_array[i].level ==
1497 : SMB_INFO_QUERY_EAS_FROM_LIST) {
1498 : uint16_t setup;
1499 : uint8_t *param;
1500 : uint8_t data[8];
1501 0 : uint8_t *rparam = NULL;
1502 0 : uint8_t *rdata = NULL;
1503 0 : uint32_t rbytes = 0;
1504 :
1505 : /* Set up an EA list with 'a' as the single name. */
1506 0 : SIVAL(data,0, 8);
1507 0 : SCVAL(data,4, 2); /* namelen. */
1508 0 : SCVAL(data,5, 'a');
1509 0 : SCVAL(data,6, '\0'); /* name. */
1510 0 : SCVAL(data,7, '\0'); /* padding. */
1511 :
1512 0 : SSVAL(&setup, 0, TRANSACT2_QPATHINFO);
1513 :
1514 0 : param = talloc_zero_array(ctx, uint8_t, 6);
1515 0 : if (param == NULL) {
1516 0 : return NT_STATUS_NO_MEMORY;
1517 : }
1518 0 : SSVAL(param, 0, SMB_INFO_QUERY_EAS_FROM_LIST);
1519 0 : param = trans2_bytes_push_str(param,
1520 0 : smbXcli_conn_use_unicode(cli_unix->conn),
1521 : fname,
1522 0 : strlen(fname)+1,
1523 : NULL);
1524 0 : if (param == NULL) {
1525 0 : return NT_STATUS_NO_MEMORY;
1526 : }
1527 :
1528 0 : status = cli_trans(ctx,
1529 : cli_unix,
1530 : SMBtrans2,
1531 : NULL,
1532 : -1,
1533 : 0,
1534 : 0,
1535 : &setup, 1, 0,
1536 0 : param, talloc_get_size(param), talloc_get_size(param),
1537 : data, 8, 0,
1538 : NULL,
1539 : NULL, 0, NULL,
1540 : &rparam, 0, &rbytes,
1541 : &rdata, 0, &rbytes);
1542 0 : TALLOC_FREE(rparam);
1543 0 : TALLOC_FREE(rdata);
1544 : } else {
1545 0 : uint8_t *rdata = NULL;
1546 0 : uint32_t num_rdata = 0;
1547 :
1548 0 : status = cli_qpathinfo(ctx,
1549 : cli_unix,
1550 : fname,
1551 0 : posix_smb1_qpath_array[i].level,
1552 : 0, /* min_rdata */
1553 : 65534, /* max_rdata */
1554 : &rdata,
1555 : &num_rdata);
1556 0 : TALLOC_FREE(rdata);
1557 : }
1558 : /*
1559 : * We don't care what came back, so long as the
1560 : * server didn't crash.
1561 : */
1562 0 : if (NT_STATUS_EQUAL(status,
1563 : NT_STATUS_CONNECTION_DISCONNECTED)) {
1564 0 : printf("cli_qpathinfo of %s failed error "
1565 : "NT_STATUS_CONNECTION_DISCONNECTED\n",
1566 : fname);
1567 0 : return status;
1568 : }
1569 :
1570 0 : printf("cli_qpathinfo info %x (%s) of %s got %s "
1571 : "(this is not an error)\n",
1572 0 : (unsigned int)posix_smb1_qpath_array[i].level,
1573 : posix_smb1_qpath_array[i].name,
1574 : fname,
1575 : nt_errstr(status));
1576 :
1577 0 : return NT_STATUS_OK;
1578 : }
1579 :
1580 : /*
1581 : Ensure we can call SMB1 getpathinfo in a symlink,
1582 : pointing to a real object or dangling. We mostly
1583 : expect errors, but the server must not crash.
1584 : */
1585 0 : bool run_posix_symlink_getpathinfo_test(int dummy)
1586 : {
1587 0 : TALLOC_CTX *frame = NULL;
1588 0 : struct cli_state *cli_unix = NULL;
1589 : NTSTATUS status;
1590 0 : uint16_t fnum = (uint16_t)-1;
1591 0 : const char *fname_real = "file_getpath_real";
1592 0 : const char *fname_real_symlink = "file_real_getpath_symlink";
1593 0 : const char *nonexist = "nonexist_getpath";
1594 0 : const char *nonexist_symlink = "dangling_getpath_symlink";
1595 0 : bool correct = false;
1596 : size_t i;
1597 :
1598 0 : frame = talloc_stackframe();
1599 :
1600 0 : printf("Starting POSIX-SYMLINK-GETPATHINFO test\n");
1601 :
1602 0 : if (!torture_open_connection(&cli_unix, 0)) {
1603 0 : TALLOC_FREE(frame);
1604 0 : return false;
1605 : }
1606 :
1607 0 : torture_conn_set_sockopt(cli_unix);
1608 :
1609 0 : status = torture_setup_unix_extensions(cli_unix);
1610 0 : if (!NT_STATUS_IS_OK(status)) {
1611 0 : TALLOC_FREE(frame);
1612 0 : return false;
1613 : }
1614 :
1615 : /* Start with a clean slate. */
1616 0 : cli_posix_unlink(cli_unix, fname_real);
1617 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1618 0 : cli_posix_unlink(cli_unix, nonexist);
1619 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1620 :
1621 : /* Create a real file. */
1622 0 : status = cli_posix_open(cli_unix,
1623 : fname_real,
1624 : O_RDWR|O_CREAT,
1625 : 0644,
1626 : &fnum);
1627 0 : if (!NT_STATUS_IS_OK(status)) {
1628 0 : printf("cli_posix_open of %s failed error %s\n",
1629 : fname_real,
1630 : nt_errstr(status));
1631 0 : goto out;
1632 : }
1633 0 : status = cli_close(cli_unix, fnum);
1634 0 : if (!NT_STATUS_IS_OK(status)) {
1635 0 : printf("cli_close failed %s\n", nt_errstr(status));
1636 0 : goto out;
1637 : }
1638 0 : fnum = (uint16_t)-1;
1639 :
1640 : /* Create symlink to real target. */
1641 0 : status = cli_posix_symlink(cli_unix,
1642 : fname_real,
1643 : fname_real_symlink);
1644 0 : if (!NT_STATUS_IS_OK(status)) {
1645 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1646 : fname_real_symlink,
1647 : fname_real,
1648 : nt_errstr(status));
1649 0 : goto out;
1650 : }
1651 :
1652 : /* Now create symlink to non-existing target. */
1653 0 : status = cli_posix_symlink(cli_unix,
1654 : nonexist,
1655 : nonexist_symlink);
1656 0 : if (!NT_STATUS_IS_OK(status)) {
1657 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1658 : nonexist_symlink,
1659 : nonexist,
1660 : nt_errstr(status));
1661 0 : goto out;
1662 : }
1663 :
1664 0 : for (i = 0; i < ARRAY_SIZE(posix_smb1_qpath_array); i++) {
1665 0 : status = do_qpath(frame,
1666 : cli_unix,
1667 : fname_real_symlink,
1668 : i);
1669 0 : if (!NT_STATUS_IS_OK(status)) {
1670 0 : goto out;
1671 : }
1672 0 : status = do_qpath(frame,
1673 : cli_unix,
1674 : nonexist_symlink,
1675 : i);
1676 0 : if (!NT_STATUS_IS_OK(status)) {
1677 0 : goto out;
1678 : }
1679 : }
1680 :
1681 0 : printf("POSIX-SYMLINK-GETPATHINFO test passed\n");
1682 0 : correct = true;
1683 :
1684 0 : out:
1685 0 : if (fnum != (uint16_t)-1) {
1686 0 : cli_close(cli_unix, fnum);
1687 : }
1688 0 : cli_posix_unlink(cli_unix, fname_real);
1689 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1690 0 : cli_posix_unlink(cli_unix, nonexist);
1691 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1692 :
1693 0 : if (!torture_close_connection(cli_unix)) {
1694 0 : correct = false;
1695 : }
1696 :
1697 0 : TALLOC_FREE(frame);
1698 0 : return correct;
1699 : }
1700 :
1701 : /* List of info levels to try with a POSIX symlink path. */
1702 :
1703 : static struct {
1704 : uint32_t level;
1705 : const char *name;
1706 : uint32_t data_len;
1707 : } posix_smb1_setpath_array[] = {
1708 : { SMB_SET_FILE_UNIX_BASIC, "SMB_SET_FILE_UNIX_BASIC", 100},
1709 : { SMB_SET_FILE_UNIX_INFO2, "SMB_SET_FILE_UNIX_INFO2", 116},
1710 : { SMB_SET_FILE_UNIX_LINK, "SMB_SET_FILE_UNIX_LINK", 8},
1711 : { SMB_SET_FILE_UNIX_HLINK, "SMB_SET_FILE_UNIX_HLINK", 8},
1712 : { SMB_SET_POSIX_ACL, "SMB_SET_POSIX_ACL", 6},
1713 : { SMB_SET_POSIX_LOCK, "SMB_SET_POSIX_LOCK", 24},
1714 : { SMB_INFO_STANDARD, "SMB_INFO_STANDARD", 12},
1715 : { SMB_INFO_SET_EA, "SMB_INFO_SET_EA", 10},
1716 : { SMB_FILE_BASIC_INFORMATION, "SMB_FILE_BASIC_INFORMATION", 36},
1717 : { SMB_SET_FILE_ALLOCATION_INFO, "SMB_SET_FILE_ALLOCATION_INFO", 8},
1718 : { SMB_SET_FILE_END_OF_FILE_INFO,"SMB_SET_FILE_END_OF_FILE_INFO",8},
1719 : { SMB_SET_FILE_DISPOSITION_INFO,"SMB_SET_FILE_DISPOSITION_INFO",1},
1720 : { SMB_FILE_POSITION_INFORMATION,"SMB_FILE_POSITION_INFORMATION",8},
1721 : { SMB_FILE_FULL_EA_INFORMATION, "SMB_FILE_FULL_EA_INFORMATION",10},
1722 : { SMB_FILE_MODE_INFORMATION, "SMB_FILE_MODE_INFORMATION", 4},
1723 : { SMB_FILE_SHORT_NAME_INFORMATION,"SMB_FILE_SHORT_NAME_INFORMATION",12},
1724 : { SMB_FILE_RENAME_INFORMATION,"SMB_FILE_RENAME_INFORMATION", 20},
1725 : { SMB_FILE_LINK_INFORMATION, "SMB_FILE_LINK_INFORMATION", 20},
1726 : };
1727 :
1728 0 : static NTSTATUS do_setpath(TALLOC_CTX *ctx,
1729 : struct cli_state *cli_unix,
1730 : const char *fname,
1731 : size_t i)
1732 : {
1733 : NTSTATUS status;
1734 0 : uint8_t *data = NULL;
1735 :
1736 0 : data = talloc_zero_array(ctx,
1737 : uint8_t,
1738 : posix_smb1_setpath_array[i].data_len);
1739 0 : if (data == NULL) {
1740 0 : return NT_STATUS_NO_MEMORY;
1741 : }
1742 :
1743 0 : status = cli_setpathinfo(cli_unix,
1744 0 : posix_smb1_setpath_array[i].level,
1745 : fname,
1746 : data,
1747 0 : posix_smb1_setpath_array[i].data_len);
1748 0 : TALLOC_FREE(data);
1749 :
1750 : /*
1751 : * We don't care what came back, so long as the
1752 : * server didn't crash.
1753 : */
1754 0 : if (NT_STATUS_EQUAL(status,
1755 : NT_STATUS_CONNECTION_DISCONNECTED)) {
1756 0 : printf("cli_setpathinfo info %x (%s) of %s failed"
1757 : "error NT_STATUS_CONNECTION_DISCONNECTED\n",
1758 0 : (unsigned int)posix_smb1_setpath_array[i].level,
1759 : posix_smb1_setpath_array[i].name,
1760 : fname);
1761 0 : return status;
1762 : }
1763 :
1764 0 : printf("cli_setpathinfo info %x (%s) of %s got %s "
1765 : "(this is not an error)\n",
1766 0 : (unsigned int)posix_smb1_setpath_array[i].level,
1767 : posix_smb1_setpath_array[i].name,
1768 : fname,
1769 : nt_errstr(status));
1770 :
1771 0 : return NT_STATUS_OK;
1772 : }
1773 :
1774 : /*
1775 : Ensure we can call SMB1 setpathinfo in a symlink,
1776 : pointing to a real object or dangling. We mostly
1777 : expect errors, but the server must not crash.
1778 : */
1779 0 : bool run_posix_symlink_setpathinfo_test(int dummy)
1780 : {
1781 0 : TALLOC_CTX *frame = NULL;
1782 0 : struct cli_state *cli_unix = NULL;
1783 : NTSTATUS status;
1784 0 : uint16_t fnum = (uint16_t)-1;
1785 0 : const char *fname_real = "file_setpath_real";
1786 0 : const char *fname_real_symlink = "file_real_setpath_symlink";
1787 0 : const char *nonexist = "nonexist_setpath";
1788 0 : const char *nonexist_symlink = "dangling_setpath_symlink";
1789 0 : bool correct = false;
1790 : size_t i;
1791 :
1792 0 : frame = talloc_stackframe();
1793 :
1794 0 : printf("Starting POSIX-SYMLINK-SETPATHINFO test\n");
1795 :
1796 0 : if (!torture_open_connection(&cli_unix, 0)) {
1797 0 : TALLOC_FREE(frame);
1798 0 : return false;
1799 : }
1800 :
1801 0 : torture_conn_set_sockopt(cli_unix);
1802 :
1803 0 : status = torture_setup_unix_extensions(cli_unix);
1804 0 : if (!NT_STATUS_IS_OK(status)) {
1805 0 : TALLOC_FREE(frame);
1806 0 : return false;
1807 : }
1808 :
1809 : /* Start with a clean slate. */
1810 0 : cli_posix_unlink(cli_unix, fname_real);
1811 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1812 0 : cli_posix_unlink(cli_unix, nonexist);
1813 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1814 :
1815 : /* Create a real file. */
1816 0 : status = cli_posix_open(cli_unix,
1817 : fname_real,
1818 : O_RDWR|O_CREAT,
1819 : 0644,
1820 : &fnum);
1821 0 : if (!NT_STATUS_IS_OK(status)) {
1822 0 : printf("cli_posix_open of %s failed error %s\n",
1823 : fname_real,
1824 : nt_errstr(status));
1825 0 : goto out;
1826 : }
1827 0 : status = cli_close(cli_unix, fnum);
1828 0 : if (!NT_STATUS_IS_OK(status)) {
1829 0 : printf("cli_close failed %s\n", nt_errstr(status));
1830 0 : goto out;
1831 : }
1832 0 : fnum = (uint16_t)-1;
1833 :
1834 : /* Create symlink to real target. */
1835 0 : status = cli_posix_symlink(cli_unix,
1836 : fname_real,
1837 : fname_real_symlink);
1838 0 : if (!NT_STATUS_IS_OK(status)) {
1839 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1840 : fname_real_symlink,
1841 : fname_real,
1842 : nt_errstr(status));
1843 0 : goto out;
1844 : }
1845 :
1846 : /* Now create symlink to non-existing target. */
1847 0 : status = cli_posix_symlink(cli_unix,
1848 : nonexist,
1849 : nonexist_symlink);
1850 0 : if (!NT_STATUS_IS_OK(status)) {
1851 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1852 : nonexist_symlink,
1853 : nonexist,
1854 : nt_errstr(status));
1855 0 : goto out;
1856 : }
1857 :
1858 0 : for (i = 0; i < ARRAY_SIZE(posix_smb1_setpath_array); i++) {
1859 0 : status = do_setpath(frame,
1860 : cli_unix,
1861 : fname_real_symlink,
1862 : i);
1863 0 : if (!NT_STATUS_IS_OK(status)) {
1864 0 : goto out;
1865 : }
1866 0 : status = do_setpath(frame,
1867 : cli_unix,
1868 : nonexist_symlink,
1869 : i);
1870 0 : if (!NT_STATUS_IS_OK(status)) {
1871 0 : goto out;
1872 : }
1873 : }
1874 :
1875 0 : printf("POSIX-SYMLINK-SETPATHINFO test passed\n");
1876 0 : correct = true;
1877 :
1878 0 : out:
1879 0 : if (fnum != (uint16_t)-1) {
1880 0 : cli_close(cli_unix, fnum);
1881 : }
1882 0 : cli_posix_unlink(cli_unix, fname_real);
1883 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1884 0 : cli_posix_unlink(cli_unix, nonexist);
1885 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1886 :
1887 0 : if (!torture_close_connection(cli_unix)) {
1888 0 : correct = false;
1889 : }
1890 :
1891 0 : TALLOC_FREE(frame);
1892 0 : return correct;
1893 : }
|