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_close 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_posix_readlink(cli_unix,
547 : state[i].name,
548 : talloc_tos(),
549 : &target);
550 0 : if (!NT_STATUS_IS_OK(status)) {
551 0 : printf("POSIX readlink on %s failed (%s)\n",
552 : state[i].name, nt_errstr(status));
553 0 : goto out;
554 : }
555 0 : if (strequal(target, state[i].target)) {
556 0 : state[i].ok = true;
557 0 : state[i].returned_size = strlen(target);
558 : }
559 : }
560 :
561 0 : if (!posix_test_entry_check(state,
562 : symlnk_dangling,
563 : true,
564 : strlen(symlnk_dst_dangling)))
565 : {
566 0 : goto out;
567 : }
568 0 : if (!posix_test_entry_check(state,
569 : symlnk_outside_share,
570 : true,
571 : strlen(symlnk_dst_outside_share)))
572 : {
573 0 : goto out;
574 : }
575 0 : if (!posix_test_entry_check(state,
576 : symlnk_in_share,
577 : true,
578 : strlen(symlnk_dst_in_share))) {
579 0 : goto out;
580 : }
581 :
582 0 : printf("POSIX-READLINK test passed\n");
583 0 : correct = true;
584 :
585 0 : out:
586 0 : cli_posix_unlink(cli_unix, file);
587 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
588 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
589 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
590 :
591 0 : if (!torture_close_connection(cli_unix)) {
592 0 : correct = false;
593 : }
594 :
595 0 : TALLOC_FREE(frame);
596 0 : return correct;
597 : }
598 :
599 : /*
600 : Test POSIX stat of symlinks
601 : */
602 0 : bool run_posix_stat_test(int dummy)
603 : {
604 0 : TALLOC_CTX *frame = NULL;
605 0 : struct cli_state *cli_unix = NULL;
606 0 : uint16_t fnum = (uint16_t)-1;
607 : NTSTATUS status;
608 0 : const char *file = "file";
609 0 : const char *symlnk_dangling = "dangling";
610 0 : const char *symlnk_dst_dangling = "xxxxxxx";
611 0 : const char *symlnk_in_share = "symlnk_in_share";
612 0 : const char *symlnk_dst_in_share = file;
613 0 : const char *symlnk_outside_share = "symlnk_outside_share";
614 0 : const char *symlnk_dst_outside_share = "/etc/passwd";
615 0 : struct posix_test_entry state[] = {
616 : {
617 : .name = symlnk_dangling,
618 : .target = symlnk_dst_dangling,
619 : .expected = symlnk_dangling,
620 : }, {
621 : .name = symlnk_in_share,
622 : .target = symlnk_dst_in_share,
623 : .expected = symlnk_in_share,
624 : }, {
625 : .name = symlnk_outside_share,
626 : .target = symlnk_dst_outside_share,
627 : .expected = symlnk_outside_share,
628 : }, {
629 : .name = NULL,
630 : }
631 : };
632 : int i;
633 0 : bool correct = false;
634 :
635 0 : frame = talloc_stackframe();
636 :
637 0 : printf("Starting POSIX-STAT test\n");
638 :
639 0 : if (!torture_open_connection(&cli_unix, 0)) {
640 0 : TALLOC_FREE(frame);
641 0 : return false;
642 : }
643 :
644 0 : torture_conn_set_sockopt(cli_unix);
645 :
646 0 : status = torture_setup_unix_extensions(cli_unix);
647 0 : if (!NT_STATUS_IS_OK(status)) {
648 0 : TALLOC_FREE(frame);
649 0 : return false;
650 : }
651 :
652 0 : cli_posix_unlink(cli_unix, file);
653 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
654 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
655 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
656 :
657 0 : status = cli_posix_open(cli_unix,
658 : file,
659 : O_RDWR|O_CREAT,
660 : 0666,
661 : &fnum);
662 0 : if (!NT_STATUS_IS_OK(status)) {
663 0 : printf("cli_posix_open of %s failed error %s\n",
664 : file,
665 : nt_errstr(status));
666 0 : goto out;
667 : }
668 :
669 0 : status = cli_close(cli_unix, fnum);
670 0 : if (!NT_STATUS_IS_OK(status)) {
671 0 : printf("cli_close failed %s\n", nt_errstr(status));
672 0 : goto out;
673 : }
674 0 : fnum = (uint16_t)-1;
675 :
676 0 : for (i = 0; state[i].name != NULL; i++) {
677 0 : status = cli_posix_symlink(cli_unix,
678 : state[i].target,
679 : state[i].name);
680 0 : if (!NT_STATUS_IS_OK(status)) {
681 0 : printf("POSIX symlink of %s failed (%s)\n",
682 : symlnk_dangling, nt_errstr(status));
683 0 : goto out;
684 : }
685 : }
686 :
687 0 : for (i = 0; state[i].name != NULL; i++) {
688 : SMB_STRUCT_STAT sbuf;
689 :
690 0 : status = cli_posix_stat(cli_unix,
691 : state[i].name,
692 : &sbuf);
693 0 : if (!NT_STATUS_IS_OK(status)) {
694 0 : printf("POSIX stat on %s failed (%s)\n",
695 : state[i].name, nt_errstr(status));
696 0 : continue;
697 : }
698 0 : state[i].ok = true;
699 0 : state[i].returned_size = sbuf.st_ex_size;
700 : }
701 :
702 0 : if (!posix_test_entry_check(state,
703 : symlnk_dangling,
704 : true,
705 : strlen(symlnk_dst_dangling)))
706 : {
707 0 : goto out;
708 : }
709 0 : if (!posix_test_entry_check(state,
710 : symlnk_outside_share,
711 : true,
712 : strlen(symlnk_dst_outside_share)))
713 : {
714 0 : goto out;
715 : }
716 0 : if (!posix_test_entry_check(state,
717 : symlnk_in_share,
718 : true,
719 : strlen(symlnk_dst_in_share))) {
720 0 : goto out;
721 : }
722 :
723 0 : printf("POSIX-STAT test passed\n");
724 0 : correct = true;
725 :
726 0 : out:
727 0 : cli_posix_unlink(cli_unix, file);
728 0 : cli_posix_unlink(cli_unix, symlnk_dangling);
729 0 : cli_posix_unlink(cli_unix, symlnk_in_share);
730 0 : cli_posix_unlink(cli_unix, symlnk_outside_share);
731 :
732 0 : if (!torture_close_connection(cli_unix)) {
733 0 : correct = false;
734 : }
735 :
736 0 : TALLOC_FREE(frame);
737 0 : return correct;
738 : }
739 :
740 : /*
741 : Test Creating files and directories directly
742 : under a symlink.
743 : */
744 0 : bool run_posix_symlink_parent_test(int dummy)
745 : {
746 0 : TALLOC_CTX *frame = NULL;
747 0 : struct cli_state *cli_unix = NULL;
748 0 : uint16_t fnum = (uint16_t)-1;
749 : NTSTATUS status;
750 0 : const char *parent_dir = "target_dir";
751 0 : const char *parent_symlink = "symlink_to_target_dir";
752 0 : const char *fname_real = "target_dir/file";
753 0 : const char *dname_real = "target_dir/dir";
754 0 : const char *fname_link = "symlink_to_target_dir/file";
755 0 : const char *dname_link = "symlink_to_target_dir/dir";
756 0 : const char *sname_link = "symlink_to_target_dir/symlink";
757 0 : const char *hname_link = "symlink_to_target_dir/hardlink";
758 0 : bool correct = false;
759 :
760 0 : frame = talloc_stackframe();
761 :
762 0 : printf("Starting POSIX-SYMLINK-PARENT test\n");
763 :
764 0 : if (!torture_open_connection(&cli_unix, 0)) {
765 0 : TALLOC_FREE(frame);
766 0 : return false;
767 : }
768 :
769 0 : torture_conn_set_sockopt(cli_unix);
770 :
771 0 : status = torture_setup_unix_extensions(cli_unix);
772 0 : if (!NT_STATUS_IS_OK(status)) {
773 0 : TALLOC_FREE(frame);
774 0 : return false;
775 : }
776 :
777 : /* Start with a clean slate. */
778 0 : cli_posix_unlink(cli_unix, fname_real);
779 0 : cli_posix_rmdir(cli_unix, dname_real);
780 0 : cli_posix_unlink(cli_unix, fname_link);
781 0 : cli_posix_rmdir(cli_unix, dname_link);
782 0 : cli_posix_unlink(cli_unix, sname_link);
783 0 : cli_posix_unlink(cli_unix, hname_link);
784 0 : cli_posix_unlink(cli_unix, parent_symlink);
785 0 : cli_posix_rmdir(cli_unix, parent_dir);
786 :
787 : /* Create parent_dir. */
788 0 : status = cli_posix_mkdir(cli_unix, parent_dir, 0777);
789 0 : if (!NT_STATUS_IS_OK(status)) {
790 0 : printf("cli_posix_mkdir of %s failed error %s\n",
791 : parent_dir,
792 : nt_errstr(status));
793 0 : goto out;
794 : }
795 : /* Create symlink to parent_dir. */
796 0 : status = cli_posix_symlink(cli_unix,
797 : parent_dir,
798 : parent_symlink);
799 0 : if (!NT_STATUS_IS_OK(status)) {
800 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
801 : parent_symlink,
802 : parent_dir,
803 : nt_errstr(status));
804 0 : goto out;
805 : }
806 : /* Try and create a directory under the symlink. */
807 0 : status = cli_posix_mkdir(cli_unix, dname_link, 0777);
808 0 : if (!NT_STATUS_IS_OK(status)) {
809 0 : printf("cli_posix_mkdir of %s failed error %s\n",
810 : dname_link,
811 : nt_errstr(status));
812 0 : goto out;
813 : }
814 : /* Try and create a file under the symlink. */
815 0 : status = cli_posix_open(cli_unix,
816 : fname_link,
817 : O_RDWR|O_CREAT,
818 : 0666,
819 : &fnum);
820 0 : if (!NT_STATUS_IS_OK(status)) {
821 0 : printf("cli_posix_open of %s failed error %s\n",
822 : fname_link,
823 : nt_errstr(status));
824 0 : goto out;
825 : }
826 0 : status = cli_close(cli_unix, fnum);
827 0 : if (!NT_STATUS_IS_OK(status)) {
828 0 : printf("cli_close failed %s\n", nt_errstr(status));
829 0 : goto out;
830 : }
831 0 : fnum = (uint16_t)-1;
832 :
833 : /* Try and create a symlink to the file under the symlink. */
834 0 : status = cli_posix_symlink(cli_unix,
835 : fname_link,
836 : sname_link);
837 0 : if (!NT_STATUS_IS_OK(status)) {
838 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
839 : sname_link,
840 : fname_link,
841 : nt_errstr(status));
842 0 : goto out;
843 : }
844 :
845 : /* Try and create a hardlink to the file under the symlink. */
846 0 : status = cli_posix_hardlink(cli_unix,
847 : fname_link,
848 : hname_link);
849 0 : if (!NT_STATUS_IS_OK(status)) {
850 0 : printf("cli_posix_hardlink of %s -> %s failed error %s\n",
851 : hname_link,
852 : fname_link,
853 : nt_errstr(status));
854 0 : goto out;
855 : }
856 :
857 : /* Ensure we can delete the symlink via the parent symlink */
858 0 : status = cli_posix_unlink(cli_unix, sname_link);
859 0 : if (!NT_STATUS_IS_OK(status)) {
860 0 : printf("cli_posix_unlink of %s failed error %s\n",
861 : sname_link,
862 : nt_errstr(status));
863 0 : goto out;
864 : }
865 :
866 : /* Ensure we can delete the hardlink via the parent symlink */
867 0 : status = cli_posix_unlink(cli_unix, hname_link);
868 0 : if (!NT_STATUS_IS_OK(status)) {
869 0 : printf("cli_posix_unlink of %s failed error %s\n",
870 : hname_link,
871 : nt_errstr(status));
872 0 : goto out;
873 : }
874 :
875 : /* Ensure we can delete the directory via the parent symlink */
876 0 : status = cli_posix_rmdir(cli_unix, dname_link);
877 0 : if (!NT_STATUS_IS_OK(status)) {
878 0 : printf("cli_posix_rmdir of %s failed error %s\n",
879 : dname_link,
880 : nt_errstr(status));
881 0 : goto out;
882 : }
883 : /* Ensure we can delete the file via the parent symlink */
884 0 : status = cli_posix_unlink(cli_unix, fname_link);
885 0 : if (!NT_STATUS_IS_OK(status)) {
886 0 : printf("cli_posix_unlink of %s failed error %s\n",
887 : fname_link,
888 : nt_errstr(status));
889 0 : goto out;
890 : }
891 :
892 0 : printf("POSIX-SYMLINK-PARENT test passed\n");
893 0 : correct = true;
894 :
895 0 : out:
896 0 : if (fnum != (uint16_t)-1) {
897 0 : cli_close(cli_unix, fnum);
898 : }
899 0 : cli_posix_unlink(cli_unix, fname_real);
900 0 : cli_posix_rmdir(cli_unix, dname_real);
901 0 : cli_posix_unlink(cli_unix, fname_link);
902 0 : cli_posix_rmdir(cli_unix, dname_link);
903 0 : cli_posix_unlink(cli_unix, sname_link);
904 0 : cli_posix_unlink(cli_unix, hname_link);
905 0 : cli_posix_unlink(cli_unix, parent_symlink);
906 0 : cli_posix_rmdir(cli_unix, parent_dir);
907 :
908 0 : if (!torture_close_connection(cli_unix)) {
909 0 : correct = false;
910 : }
911 :
912 0 : TALLOC_FREE(frame);
913 0 : return correct;
914 : }
915 :
916 : /*
917 : Ensure we get an error when doing chmod on a symlink,
918 : whether it is pointing to a real object or dangling.
919 : */
920 0 : bool run_posix_symlink_chmod_test(int dummy)
921 : {
922 0 : TALLOC_CTX *frame = NULL;
923 0 : struct cli_state *cli_unix = NULL;
924 : NTSTATUS status;
925 0 : uint16_t fnum = (uint16_t)-1;
926 0 : const char *fname_real = "file_real";
927 0 : const char *fname_real_symlink = "file_real_symlink";
928 0 : const char *nonexist = "nonexist";
929 0 : const char *nonexist_symlink = "dangling_symlink";
930 0 : bool correct = false;
931 :
932 0 : frame = talloc_stackframe();
933 :
934 0 : printf("Starting POSIX-SYMLINK-CHMOD test\n");
935 :
936 0 : if (!torture_open_connection(&cli_unix, 0)) {
937 0 : TALLOC_FREE(frame);
938 0 : return false;
939 : }
940 :
941 0 : torture_conn_set_sockopt(cli_unix);
942 :
943 0 : status = torture_setup_unix_extensions(cli_unix);
944 0 : if (!NT_STATUS_IS_OK(status)) {
945 0 : TALLOC_FREE(frame);
946 0 : return false;
947 : }
948 :
949 : /* Start with a clean slate. */
950 0 : cli_posix_unlink(cli_unix, fname_real);
951 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
952 0 : cli_posix_unlink(cli_unix, nonexist);
953 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
954 :
955 : /* Create a real file. */
956 0 : status = cli_posix_open(cli_unix,
957 : fname_real,
958 : O_RDWR|O_CREAT,
959 : 0644,
960 : &fnum);
961 0 : if (!NT_STATUS_IS_OK(status)) {
962 0 : printf("cli_posix_open of %s failed error %s\n",
963 : fname_real,
964 : nt_errstr(status));
965 0 : goto out;
966 : }
967 0 : status = cli_close(cli_unix, fnum);
968 0 : if (!NT_STATUS_IS_OK(status)) {
969 0 : printf("cli_close failed %s\n", nt_errstr(status));
970 0 : goto out;
971 : }
972 0 : fnum = (uint16_t)-1;
973 :
974 : /* Create symlink to real target. */
975 0 : status = cli_posix_symlink(cli_unix,
976 : fname_real,
977 : fname_real_symlink);
978 0 : if (!NT_STATUS_IS_OK(status)) {
979 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
980 : fname_real_symlink,
981 : fname_real,
982 : nt_errstr(status));
983 0 : goto out;
984 : }
985 :
986 : /* We should not be able to chmod symlinks that point to something. */
987 0 : status = cli_posix_chmod(cli_unix, fname_real_symlink, 0777);
988 :
989 : /* This should fail with something other than server crashed. */
990 0 : if (NT_STATUS_IS_OK(status)) {
991 0 : printf("cli_posix_chmod of %s succeeded (should have failed)\n",
992 : fname_real_symlink);
993 0 : goto out;
994 : }
995 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED)) {
996 : /* Oops. Server crashed. */
997 0 : printf("cli_posix_chmod of %s failed error %s\n",
998 : fname_real_symlink,
999 : nt_errstr(status));
1000 0 : goto out;
1001 : }
1002 : /* Any other failure is ok. */
1003 :
1004 : /* Now create symlink to non-existing target. */
1005 0 : status = cli_posix_symlink(cli_unix,
1006 : nonexist,
1007 : nonexist_symlink);
1008 0 : if (!NT_STATUS_IS_OK(status)) {
1009 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1010 : nonexist_symlink,
1011 : nonexist,
1012 : nt_errstr(status));
1013 0 : goto out;
1014 : }
1015 :
1016 : /* We should not be able to chmod symlinks that point to nothing. */
1017 0 : status = cli_posix_chmod(cli_unix, nonexist_symlink, 0777);
1018 :
1019 : /* This should fail with something other than server crashed. */
1020 0 : if (NT_STATUS_IS_OK(status)) {
1021 0 : printf("cli_posix_chmod of %s succeeded (should have failed)\n",
1022 : nonexist_symlink);
1023 0 : goto out;
1024 : }
1025 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED)) {
1026 : /* Oops. Server crashed. */
1027 0 : printf("cli_posix_chmod of %s failed error %s\n",
1028 : nonexist_symlink,
1029 : nt_errstr(status));
1030 0 : goto out;
1031 : }
1032 :
1033 : /* Any other failure is ok. */
1034 0 : printf("POSIX-SYMLINK-CHMOD test passed (expected failure was %s)\n",
1035 : nt_errstr(status));
1036 0 : correct = true;
1037 :
1038 0 : out:
1039 0 : if (fnum != (uint16_t)-1) {
1040 0 : cli_close(cli_unix, fnum);
1041 : }
1042 0 : cli_posix_unlink(cli_unix, fname_real);
1043 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1044 0 : cli_posix_unlink(cli_unix, nonexist);
1045 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1046 :
1047 0 : if (!torture_close_connection(cli_unix)) {
1048 0 : correct = false;
1049 : }
1050 :
1051 0 : TALLOC_FREE(frame);
1052 0 : return correct;
1053 : }
1054 :
1055 : /*
1056 : Ensure we get an ACL containing OI|IO ACE entries
1057 : after we add a default POSIX ACL to a directory.
1058 : This will only ever be an SMB1 test as it depends
1059 : on POSIX ACL semantics.
1060 : */
1061 0 : bool run_posix_dir_default_acl_test(int dummy)
1062 : {
1063 0 : TALLOC_CTX *frame = NULL;
1064 0 : struct cli_state *cli_unix = NULL;
1065 : NTSTATUS status;
1066 0 : uint16_t fnum = (uint16_t)-1;
1067 0 : const char *dname = "dir_with_default_acl";
1068 0 : bool correct = false;
1069 : SMB_STRUCT_STAT sbuf;
1070 0 : size_t acl_size = 0;
1071 0 : char *aclbuf = NULL;
1072 0 : size_t num_file_acls = 0;
1073 0 : size_t num_dir_acls = 0;
1074 : size_t expected_buflen;
1075 0 : uint8_t def_acl[SMB_POSIX_ACL_HEADER_SIZE +
1076 : 5*SMB_POSIX_ACL_ENTRY_SIZE] = {0};
1077 0 : uint8_t *p = NULL;
1078 0 : uint32_t i = 0;
1079 0 : struct security_descriptor *sd = NULL;
1080 0 : bool got_inherit = false;
1081 :
1082 0 : frame = talloc_stackframe();
1083 :
1084 0 : printf("Starting POSIX-DIR-DEFAULT-ACL test\n");
1085 :
1086 0 : if (!torture_open_connection(&cli_unix, 0)) {
1087 0 : TALLOC_FREE(frame);
1088 0 : return false;
1089 : }
1090 :
1091 0 : torture_conn_set_sockopt(cli_unix);
1092 :
1093 0 : status = torture_setup_unix_extensions(cli_unix);
1094 0 : if (!NT_STATUS_IS_OK(status)) {
1095 0 : TALLOC_FREE(frame);
1096 0 : return false;
1097 : }
1098 :
1099 : /* Start with a clean slate. */
1100 0 : cli_posix_unlink(cli_unix, dname);
1101 0 : cli_posix_rmdir(cli_unix, dname);
1102 :
1103 0 : status = cli_posix_mkdir(cli_unix, dname, 0777);
1104 0 : if (!NT_STATUS_IS_OK(status)) {
1105 0 : printf("cli_posix_mkdir of %s failed error %s\n",
1106 : dname,
1107 : nt_errstr(status));
1108 0 : goto out;
1109 : }
1110 :
1111 : /* Do a posix stat to get the owner. */
1112 0 : status = cli_posix_stat(cli_unix, dname, &sbuf);
1113 0 : if (!NT_STATUS_IS_OK(status)) {
1114 0 : printf("cli_posix_stat of %s failed %s\n",
1115 : dname,
1116 : nt_errstr(status));
1117 0 : goto out;
1118 : }
1119 :
1120 : /* Get the ACL on the directory. */
1121 0 : status = cli_posix_getacl(cli_unix, dname, frame, &acl_size, &aclbuf);
1122 0 : if (!NT_STATUS_IS_OK(status)) {
1123 0 : printf("cli_posix_getacl on %s failed %s\n",
1124 : dname,
1125 : nt_errstr(status));
1126 0 : goto out;
1127 : }
1128 :
1129 0 : if (acl_size < 6 || SVAL(aclbuf,0) != SMB_POSIX_ACL_VERSION) {
1130 0 : printf("%s, unknown POSIX acl version %u.\n",
1131 : dname,
1132 0 : (unsigned int)CVAL(aclbuf,0) );
1133 0 : goto out;
1134 : }
1135 :
1136 0 : num_file_acls = SVAL(aclbuf,2);
1137 0 : num_dir_acls = SVAL(aclbuf,4);
1138 :
1139 : /*
1140 : * No overflow check, num_*_acls comes from a 16-bit value,
1141 : * and we expect expected_buflen (size_t) to be of at least 32
1142 : * bit.
1143 : */
1144 0 : expected_buflen = SMB_POSIX_ACL_HEADER_SIZE +
1145 0 : SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls);
1146 :
1147 0 : if (acl_size != expected_buflen) {
1148 0 : printf("%s, incorrect POSIX acl buffer size "
1149 : "(should be %zu, was %zu).\n",
1150 : dname,
1151 : expected_buflen,
1152 : acl_size);
1153 0 : goto out;
1154 : }
1155 :
1156 0 : if (num_dir_acls != 0) {
1157 0 : printf("%s, POSIX default acl already exists"
1158 : "(should be 0, was %zu).\n",
1159 : dname,
1160 : num_dir_acls);
1161 0 : goto out;
1162 : }
1163 :
1164 : /*
1165 : * Get the Windows ACL on the directory.
1166 : * Make sure there are no inheritable entries.
1167 : */
1168 0 : status = cli_ntcreate(cli_unix,
1169 : dname,
1170 : 0,
1171 : SEC_STD_READ_CONTROL,
1172 : 0,
1173 : FILE_SHARE_READ|
1174 : FILE_SHARE_WRITE|
1175 : FILE_SHARE_DELETE,
1176 : FILE_OPEN,
1177 : FILE_DIRECTORY_FILE,
1178 : 0x0,
1179 : &fnum,
1180 : NULL);
1181 0 : if (!NT_STATUS_IS_OK(status)) {
1182 0 : printf("Failed to open directory %s: %s\n",
1183 : dname,
1184 : nt_errstr(status));
1185 0 : goto out;
1186 : }
1187 :
1188 0 : status = cli_query_security_descriptor(cli_unix,
1189 : fnum,
1190 : SECINFO_DACL,
1191 : frame,
1192 : &sd);
1193 0 : if (!NT_STATUS_IS_OK(status)) {
1194 0 : printf("Failed to get security descriptor on directory %s: %s\n",
1195 : dname,
1196 : nt_errstr(status));
1197 0 : goto out;
1198 : }
1199 :
1200 0 : for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1201 0 : struct security_ace *ace = &sd->dacl->aces[i];
1202 0 : if (ace->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
1203 : SEC_ACE_FLAG_CONTAINER_INHERIT)) {
1204 0 : printf("security descritor on directory %s already "
1205 : "contains inheritance flags\n",
1206 : dname);
1207 0 : sec_desc_print(NULL, stdout, sd, true);
1208 0 : goto out;
1209 : }
1210 : }
1211 :
1212 0 : TALLOC_FREE(sd);
1213 :
1214 : /* Construct a new default ACL. */
1215 0 : SSVAL(def_acl,0,SMB_POSIX_ACL_VERSION);
1216 0 : SSVAL(def_acl,2,SMB_POSIX_IGNORE_ACE_ENTRIES);
1217 0 : SSVAL(def_acl,4,5); /* num_dir_acls. */
1218 :
1219 0 : p = def_acl + SMB_POSIX_ACL_HEADER_SIZE;
1220 :
1221 : /* USER_OBJ. */
1222 0 : SCVAL(p,0,SMB_POSIX_ACL_USER_OBJ); /* tagtype. */
1223 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1224 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1225 :
1226 : /* GROUP_OBJ. */
1227 0 : SCVAL(p,0,SMB_POSIX_ACL_GROUP_OBJ); /* tagtype. */
1228 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1229 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1230 :
1231 : /* OTHER. */
1232 0 : SCVAL(p,0,SMB_POSIX_ACL_OTHER); /* tagtype. */
1233 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1234 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1235 :
1236 : /* Explicit user. */
1237 0 : SCVAL(p,0,SMB_POSIX_ACL_USER); /* tagtype. */
1238 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1239 0 : SIVAL(p,2,sbuf.st_ex_uid);
1240 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1241 :
1242 : /* MASK. */
1243 0 : SCVAL(p,0,SMB_POSIX_ACL_MASK); /* tagtype. */
1244 0 : SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE);
1245 0 : p += SMB_POSIX_ACL_ENTRY_SIZE;
1246 :
1247 : /* Set the POSIX default ACL. */
1248 0 : status = cli_posix_setacl(cli_unix, dname, def_acl, sizeof(def_acl));
1249 0 : if (!NT_STATUS_IS_OK(status)) {
1250 0 : printf("cli_posix_setacl on %s failed %s\n",
1251 : dname,
1252 : nt_errstr(status));
1253 0 : goto out;
1254 : }
1255 :
1256 : /*
1257 : * Get the Windows ACL on the directory again.
1258 : * Now there should be inheritable entries.
1259 : */
1260 :
1261 0 : status = cli_query_security_descriptor(cli_unix,
1262 : fnum,
1263 : SECINFO_DACL,
1264 : frame,
1265 : &sd);
1266 0 : if (!NT_STATUS_IS_OK(status)) {
1267 0 : printf("Failed (2) to get security descriptor "
1268 : "on directory %s: %s\n",
1269 : dname,
1270 : nt_errstr(status));
1271 0 : goto out;
1272 : }
1273 :
1274 0 : for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1275 0 : struct security_ace *ace = &sd->dacl->aces[i];
1276 0 : if (ace->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
1277 : SEC_ACE_FLAG_CONTAINER_INHERIT)) {
1278 0 : got_inherit = true;
1279 0 : break;
1280 : }
1281 : }
1282 :
1283 0 : if (!got_inherit) {
1284 0 : printf("security descritor on directory %s does not "
1285 : "contain inheritance flags\n",
1286 : dname);
1287 0 : sec_desc_print(NULL, stdout, sd, true);
1288 0 : goto out;
1289 : }
1290 :
1291 0 : cli_close(cli_unix, fnum);
1292 0 : fnum = (uint16_t)-1;
1293 0 : printf("POSIX-DIR-DEFAULT-ACL test passed\n");
1294 0 : correct = true;
1295 :
1296 0 : out:
1297 :
1298 0 : TALLOC_FREE(sd);
1299 :
1300 0 : if (fnum != (uint16_t)-1) {
1301 0 : cli_close(cli_unix, fnum);
1302 : }
1303 0 : cli_posix_unlink(cli_unix, dname);
1304 0 : cli_posix_rmdir(cli_unix, dname);
1305 :
1306 0 : if (!torture_close_connection(cli_unix)) {
1307 0 : correct = false;
1308 : }
1309 :
1310 0 : TALLOC_FREE(frame);
1311 0 : return correct;
1312 : }
1313 :
1314 : /*
1315 : Ensure we can rename a symlink whether it is
1316 : pointing to a real object or dangling.
1317 : */
1318 0 : bool run_posix_symlink_rename_test(int dummy)
1319 : {
1320 0 : TALLOC_CTX *frame = NULL;
1321 0 : struct cli_state *cli_unix = NULL;
1322 : NTSTATUS status;
1323 0 : uint16_t fnum = (uint16_t)-1;
1324 0 : const char *fname_real = "file_real";
1325 0 : const char *fname_real_symlink = "file_real_symlink";
1326 0 : const char *fname_real_symlink_newname = "rename_file_real_symlink";
1327 0 : const char *nonexist = "nonexist";
1328 0 : const char *nonexist_symlink = "dangling_symlink";
1329 0 : const char *nonexist_symlink_newname = "dangling_symlink_rename";
1330 0 : bool correct = false;
1331 :
1332 0 : frame = talloc_stackframe();
1333 :
1334 0 : printf("Starting POSIX-SYMLINK-RENAME test\n");
1335 :
1336 0 : if (!torture_open_connection(&cli_unix, 0)) {
1337 0 : TALLOC_FREE(frame);
1338 0 : return false;
1339 : }
1340 :
1341 0 : torture_conn_set_sockopt(cli_unix);
1342 :
1343 0 : status = torture_setup_unix_extensions(cli_unix);
1344 0 : if (!NT_STATUS_IS_OK(status)) {
1345 0 : TALLOC_FREE(frame);
1346 0 : return false;
1347 : }
1348 :
1349 : /* Start with a clean slate. */
1350 0 : cli_posix_unlink(cli_unix, fname_real);
1351 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1352 0 : cli_posix_unlink(cli_unix, fname_real_symlink_newname);
1353 0 : cli_posix_unlink(cli_unix, nonexist);
1354 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1355 0 : cli_posix_unlink(cli_unix, nonexist_symlink_newname);
1356 :
1357 : /* Create a real file. */
1358 0 : status = cli_posix_open(cli_unix,
1359 : fname_real,
1360 : O_RDWR|O_CREAT,
1361 : 0644,
1362 : &fnum);
1363 0 : if (!NT_STATUS_IS_OK(status)) {
1364 0 : printf("cli_posix_open of %s failed error %s\n",
1365 : fname_real,
1366 : nt_errstr(status));
1367 0 : goto out;
1368 : }
1369 0 : status = cli_close(cli_unix, fnum);
1370 0 : if (!NT_STATUS_IS_OK(status)) {
1371 0 : printf("cli_close failed %s\n", nt_errstr(status));
1372 0 : goto out;
1373 : }
1374 0 : fnum = (uint16_t)-1;
1375 :
1376 : /* Create symlink to real target. */
1377 0 : status = cli_posix_symlink(cli_unix,
1378 : fname_real,
1379 : fname_real_symlink);
1380 0 : if (!NT_STATUS_IS_OK(status)) {
1381 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1382 : fname_real_symlink,
1383 : fname_real,
1384 : nt_errstr(status));
1385 0 : goto out;
1386 : }
1387 :
1388 : /* Ensure we can rename the symlink to the real file. */
1389 0 : status = cli_rename(cli_unix,
1390 : fname_real_symlink,
1391 : fname_real_symlink_newname,
1392 : false);
1393 0 : if (!NT_STATUS_IS_OK(status)) {
1394 0 : printf("cli_rename of %s -> %s failed %s\n",
1395 : fname_real_symlink,
1396 : fname_real_symlink_newname,
1397 : nt_errstr(status));
1398 0 : goto out;
1399 : }
1400 :
1401 : /* Now create symlink to non-existing target. */
1402 0 : status = cli_posix_symlink(cli_unix,
1403 : nonexist,
1404 : nonexist_symlink);
1405 0 : if (!NT_STATUS_IS_OK(status)) {
1406 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1407 : nonexist_symlink,
1408 : nonexist,
1409 : nt_errstr(status));
1410 0 : goto out;
1411 : }
1412 :
1413 : /* Ensure we can rename the dangling symlink. */
1414 0 : status = cli_rename(cli_unix,
1415 : nonexist_symlink,
1416 : nonexist_symlink_newname,
1417 : false);
1418 0 : if (!NT_STATUS_IS_OK(status)) {
1419 0 : printf("cli_rename of %s -> %s failed %s\n",
1420 : nonexist_symlink,
1421 : nonexist_symlink_newname,
1422 : nt_errstr(status));
1423 0 : goto out;
1424 : }
1425 :
1426 0 : printf("POSIX-SYMLINK-RENAME test passed\n");
1427 0 : correct = true;
1428 :
1429 0 : out:
1430 0 : if (fnum != (uint16_t)-1) {
1431 0 : cli_close(cli_unix, fnum);
1432 : }
1433 0 : cli_posix_unlink(cli_unix, fname_real);
1434 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1435 0 : cli_posix_unlink(cli_unix, fname_real_symlink_newname);
1436 0 : cli_posix_unlink(cli_unix, nonexist);
1437 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1438 0 : cli_posix_unlink(cli_unix, nonexist_symlink_newname);
1439 :
1440 0 : if (!torture_close_connection(cli_unix)) {
1441 0 : correct = false;
1442 : }
1443 :
1444 0 : TALLOC_FREE(frame);
1445 0 : return correct;
1446 : }
1447 :
1448 : /* List of info levels to try with a POSIX symlink path. */
1449 :
1450 : static struct {
1451 : uint32_t level;
1452 : const char *name;
1453 : } posix_smb1_qpath_array[] = {
1454 : { SMB_INFO_STANDARD, "SMB_INFO_STANDARD"},
1455 : { SMB_INFO_QUERY_EA_SIZE, "SMB_INFO_QUERY_EA_SIZE"},
1456 : { SMB_INFO_IS_NAME_VALID, "SMB_INFO_IS_NAME_VALID"},
1457 : { SMB_INFO_QUERY_EAS_FROM_LIST, "SMB_INFO_QUERY_EAS_FROM_LIST"},
1458 : { SMB_INFO_QUERY_ALL_EAS, "SMB_INFO_QUERY_ALL_EAS"},
1459 : { SMB_FILE_BASIC_INFORMATION, "SMB_FILE_BASIC_INFORMATION"},
1460 : { SMB_FILE_STANDARD_INFORMATION, "SMB_FILE_STANDARD_INFORMATION"},
1461 : { SMB_FILE_EA_INFORMATION, "SMB_FILE_EA_INFORMATION"},
1462 : { SMB_FILE_ALTERNATE_NAME_INFORMATION,"SMB_FILE_ALTERNATE_NAME_INFORMATION"},
1463 : { SMB_QUERY_FILE_NAME_INFO, "SMB_QUERY_FILE_NAME_INFO"},
1464 : { SMB_FILE_NORMALIZED_NAME_INFORMATION,"SMB_FILE_NORMALIZED_NAME_INFORMATION"},
1465 : { SMB_FILE_ALLOCATION_INFORMATION, "SMB_FILE_ALLOCATION_INFORMATION"},
1466 : { SMB_FILE_END_OF_FILE_INFORMATION, "SMB_FILE_END_OF_FILE_INFORMATION"},
1467 : { SMB_FILE_ALL_INFORMATION, "SMB_FILE_ALL_INFORMATION"},
1468 : { SMB_FILE_INTERNAL_INFORMATION, "SMB_FILE_INTERNAL_INFORMATION"},
1469 : { SMB_FILE_ACCESS_INFORMATION, "SMB_FILE_ACCESS_INFORMATION"},
1470 : { SMB_FILE_NAME_INFORMATION, "SMB_FILE_NAME_INFORMATION"},
1471 : { SMB_FILE_DISPOSITION_INFORMATION, "SMB_FILE_DISPOSITION_INFORMATION"},
1472 : { SMB_FILE_POSITION_INFORMATION, "SMB_FILE_POSITION_INFORMATION"},
1473 : { SMB_FILE_MODE_INFORMATION, "SMB_FILE_MODE_INFORMATION"},
1474 : { SMB_FILE_ALIGNMENT_INFORMATION, "SMB_FILE_ALIGNMENT_INFORMATION"},
1475 : { SMB_FILE_STREAM_INFORMATION, "SMB_FILE_STREAM_INFORMATION"},
1476 : { SMB_FILE_COMPRESSION_INFORMATION, "SMB_FILE_COMPRESSION_INFORMATION"},
1477 : { SMB_FILE_NETWORK_OPEN_INFORMATION, "SMB_FILE_NETWORK_OPEN_INFORMATION"},
1478 : { SMB_FILE_ATTRIBUTE_TAG_INFORMATION, "SMB_FILE_ATTRIBUTE_TAG_INFORMATION"},
1479 : { SMB_QUERY_FILE_UNIX_BASIC, "SMB_QUERY_FILE_UNIX_BASIC"},
1480 : { SMB_QUERY_FILE_UNIX_INFO2, "SMB_QUERY_FILE_UNIX_INFO2"},
1481 : { SMB_QUERY_FILE_UNIX_LINK, "SMB_QUERY_FILE_UNIX_LINK"},
1482 : { SMB_QUERY_POSIX_ACL, "SMB_QUERY_POSIX_ACL"},
1483 : { SMB_QUERY_POSIX_LOCK, "SMB_QUERY_POSIX_LOCK"},
1484 : };
1485 :
1486 0 : static NTSTATUS do_qpath(TALLOC_CTX *ctx,
1487 : struct cli_state *cli_unix,
1488 : const char *fname,
1489 : size_t i)
1490 : {
1491 : NTSTATUS status;
1492 :
1493 0 : if (posix_smb1_qpath_array[i].level ==
1494 : SMB_INFO_QUERY_EAS_FROM_LIST) {
1495 : uint16_t setup;
1496 : uint8_t *param;
1497 : uint8_t data[8];
1498 0 : uint8_t *rparam = NULL;
1499 0 : uint8_t *rdata = NULL;
1500 0 : uint32_t rbytes = 0;
1501 :
1502 : /* Set up an EA list with 'a' as the single name. */
1503 0 : SIVAL(data,0, 8);
1504 0 : SCVAL(data,4, 2); /* namelen. */
1505 0 : SCVAL(data,5, 'a');
1506 0 : SCVAL(data,6, '\0'); /* name. */
1507 0 : SCVAL(data,7, '\0'); /* padding. */
1508 :
1509 0 : SSVAL(&setup, 0, TRANSACT2_QPATHINFO);
1510 :
1511 0 : param = talloc_zero_array(ctx, uint8_t, 6);
1512 0 : if (param == NULL) {
1513 0 : return NT_STATUS_NO_MEMORY;
1514 : }
1515 0 : SSVAL(param, 0, SMB_INFO_QUERY_EAS_FROM_LIST);
1516 0 : param = trans2_bytes_push_str(param,
1517 0 : smbXcli_conn_use_unicode(cli_unix->conn),
1518 : fname,
1519 0 : strlen(fname)+1,
1520 : NULL);
1521 0 : if (param == NULL) {
1522 0 : return NT_STATUS_NO_MEMORY;
1523 : }
1524 :
1525 0 : status = cli_trans(ctx,
1526 : cli_unix,
1527 : SMBtrans2,
1528 : NULL,
1529 : -1,
1530 : 0,
1531 : 0,
1532 : &setup, 1, 0,
1533 0 : param, talloc_get_size(param), talloc_get_size(param),
1534 : data, 8, 0,
1535 : NULL,
1536 : NULL, 0, NULL,
1537 : &rparam, 0, &rbytes,
1538 : &rdata, 0, &rbytes);
1539 0 : TALLOC_FREE(rparam);
1540 0 : TALLOC_FREE(rdata);
1541 : } else {
1542 0 : uint8_t *rdata = NULL;
1543 0 : uint32_t num_rdata = 0;
1544 :
1545 0 : status = cli_qpathinfo(ctx,
1546 : cli_unix,
1547 : fname,
1548 0 : posix_smb1_qpath_array[i].level,
1549 : 0, /* min_rdata */
1550 : 65534, /* max_rdata */
1551 : &rdata,
1552 : &num_rdata);
1553 0 : TALLOC_FREE(rdata);
1554 : }
1555 : /*
1556 : * We don't care what came back, so long as the
1557 : * server didn't crash.
1558 : */
1559 0 : if (NT_STATUS_EQUAL(status,
1560 : NT_STATUS_CONNECTION_DISCONNECTED)) {
1561 0 : printf("cli_qpathinfo of %s failed error "
1562 : "NT_STATUS_CONNECTION_DISCONNECTED\n",
1563 : fname);
1564 0 : return status;
1565 : }
1566 :
1567 0 : printf("cli_qpathinfo info %x (%s) of %s got %s "
1568 : "(this is not an error)\n",
1569 0 : (unsigned int)posix_smb1_qpath_array[i].level,
1570 : posix_smb1_qpath_array[i].name,
1571 : fname,
1572 : nt_errstr(status));
1573 :
1574 0 : return NT_STATUS_OK;
1575 : }
1576 :
1577 : /*
1578 : Ensure we can call SMB1 getpathinfo in a symlink,
1579 : pointing to a real object or dangling. We mostly
1580 : expect errors, but the server must not crash.
1581 : */
1582 0 : bool run_posix_symlink_getpathinfo_test(int dummy)
1583 : {
1584 0 : TALLOC_CTX *frame = NULL;
1585 0 : struct cli_state *cli_unix = NULL;
1586 : NTSTATUS status;
1587 0 : uint16_t fnum = (uint16_t)-1;
1588 0 : const char *fname_real = "file_getpath_real";
1589 0 : const char *fname_real_symlink = "file_real_getpath_symlink";
1590 0 : const char *nonexist = "nonexist_getpath";
1591 0 : const char *nonexist_symlink = "dangling_getpath_symlink";
1592 0 : bool correct = false;
1593 : size_t i;
1594 :
1595 0 : frame = talloc_stackframe();
1596 :
1597 0 : printf("Starting POSIX-SYMLINK-GETPATHINFO test\n");
1598 :
1599 0 : if (!torture_open_connection(&cli_unix, 0)) {
1600 0 : TALLOC_FREE(frame);
1601 0 : return false;
1602 : }
1603 :
1604 0 : torture_conn_set_sockopt(cli_unix);
1605 :
1606 0 : status = torture_setup_unix_extensions(cli_unix);
1607 0 : if (!NT_STATUS_IS_OK(status)) {
1608 0 : TALLOC_FREE(frame);
1609 0 : return false;
1610 : }
1611 :
1612 : /* Start with a clean slate. */
1613 0 : cli_posix_unlink(cli_unix, fname_real);
1614 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1615 0 : cli_posix_unlink(cli_unix, nonexist);
1616 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1617 :
1618 : /* Create a real file. */
1619 0 : status = cli_posix_open(cli_unix,
1620 : fname_real,
1621 : O_RDWR|O_CREAT,
1622 : 0644,
1623 : &fnum);
1624 0 : if (!NT_STATUS_IS_OK(status)) {
1625 0 : printf("cli_posix_open of %s failed error %s\n",
1626 : fname_real,
1627 : nt_errstr(status));
1628 0 : goto out;
1629 : }
1630 0 : status = cli_close(cli_unix, fnum);
1631 0 : if (!NT_STATUS_IS_OK(status)) {
1632 0 : printf("cli_close failed %s\n", nt_errstr(status));
1633 0 : goto out;
1634 : }
1635 0 : fnum = (uint16_t)-1;
1636 :
1637 : /* Create symlink to real target. */
1638 0 : status = cli_posix_symlink(cli_unix,
1639 : fname_real,
1640 : fname_real_symlink);
1641 0 : if (!NT_STATUS_IS_OK(status)) {
1642 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1643 : fname_real_symlink,
1644 : fname_real,
1645 : nt_errstr(status));
1646 0 : goto out;
1647 : }
1648 :
1649 : /* Now create symlink to non-existing target. */
1650 0 : status = cli_posix_symlink(cli_unix,
1651 : nonexist,
1652 : nonexist_symlink);
1653 0 : if (!NT_STATUS_IS_OK(status)) {
1654 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1655 : nonexist_symlink,
1656 : nonexist,
1657 : nt_errstr(status));
1658 0 : goto out;
1659 : }
1660 :
1661 0 : for (i = 0; i < ARRAY_SIZE(posix_smb1_qpath_array); i++) {
1662 0 : status = do_qpath(frame,
1663 : cli_unix,
1664 : fname_real_symlink,
1665 : i);
1666 0 : if (!NT_STATUS_IS_OK(status)) {
1667 0 : goto out;
1668 : }
1669 0 : status = do_qpath(frame,
1670 : cli_unix,
1671 : nonexist_symlink,
1672 : i);
1673 0 : if (!NT_STATUS_IS_OK(status)) {
1674 0 : goto out;
1675 : }
1676 : }
1677 :
1678 0 : printf("POSIX-SYMLINK-GETPATHINFO test passed\n");
1679 0 : correct = true;
1680 :
1681 0 : out:
1682 0 : if (fnum != (uint16_t)-1) {
1683 0 : cli_close(cli_unix, fnum);
1684 : }
1685 0 : cli_posix_unlink(cli_unix, fname_real);
1686 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1687 0 : cli_posix_unlink(cli_unix, nonexist);
1688 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1689 :
1690 0 : if (!torture_close_connection(cli_unix)) {
1691 0 : correct = false;
1692 : }
1693 :
1694 0 : TALLOC_FREE(frame);
1695 0 : return correct;
1696 : }
1697 :
1698 : /* List of info levels to try with a POSIX symlink path. */
1699 :
1700 : static struct {
1701 : uint32_t level;
1702 : const char *name;
1703 : uint32_t data_len;
1704 : } posix_smb1_setpath_array[] = {
1705 : { SMB_SET_FILE_UNIX_BASIC, "SMB_SET_FILE_UNIX_BASIC", 100},
1706 : { SMB_SET_FILE_UNIX_INFO2, "SMB_SET_FILE_UNIX_INFO2", 116},
1707 : { SMB_SET_FILE_UNIX_LINK, "SMB_SET_FILE_UNIX_LINK", 8},
1708 : { SMB_SET_FILE_UNIX_HLINK, "SMB_SET_FILE_UNIX_HLINK", 8},
1709 : { SMB_SET_POSIX_ACL, "SMB_SET_POSIX_ACL", 6},
1710 : { SMB_SET_POSIX_LOCK, "SMB_SET_POSIX_LOCK", 24},
1711 : { SMB_INFO_STANDARD, "SMB_INFO_STANDARD", 12},
1712 : { SMB_INFO_SET_EA, "SMB_INFO_SET_EA", 10},
1713 : { SMB_FILE_BASIC_INFORMATION, "SMB_FILE_BASIC_INFORMATION", 36},
1714 : { SMB_SET_FILE_ALLOCATION_INFO, "SMB_SET_FILE_ALLOCATION_INFO", 8},
1715 : { SMB_SET_FILE_END_OF_FILE_INFO,"SMB_SET_FILE_END_OF_FILE_INFO",8},
1716 : { SMB_SET_FILE_DISPOSITION_INFO,"SMB_SET_FILE_DISPOSITION_INFO",1},
1717 : { SMB_FILE_POSITION_INFORMATION,"SMB_FILE_POSITION_INFORMATION",8},
1718 : { SMB_FILE_FULL_EA_INFORMATION, "SMB_FILE_FULL_EA_INFORMATION",10},
1719 : { SMB_FILE_MODE_INFORMATION, "SMB_FILE_MODE_INFORMATION", 4},
1720 : { SMB_FILE_SHORT_NAME_INFORMATION,"SMB_FILE_SHORT_NAME_INFORMATION",12},
1721 : { SMB_FILE_RENAME_INFORMATION,"SMB_FILE_RENAME_INFORMATION", 20},
1722 : { SMB_FILE_LINK_INFORMATION, "SMB_FILE_LINK_INFORMATION", 20},
1723 : };
1724 :
1725 0 : static NTSTATUS do_setpath(TALLOC_CTX *ctx,
1726 : struct cli_state *cli_unix,
1727 : const char *fname,
1728 : size_t i)
1729 : {
1730 : NTSTATUS status;
1731 0 : uint8_t *data = NULL;
1732 :
1733 0 : data = talloc_zero_array(ctx,
1734 : uint8_t,
1735 : posix_smb1_setpath_array[i].data_len);
1736 0 : if (data == NULL) {
1737 0 : return NT_STATUS_NO_MEMORY;
1738 : }
1739 :
1740 0 : status = cli_setpathinfo(cli_unix,
1741 0 : posix_smb1_setpath_array[i].level,
1742 : fname,
1743 : data,
1744 0 : posix_smb1_setpath_array[i].data_len);
1745 0 : TALLOC_FREE(data);
1746 :
1747 : /*
1748 : * We don't care what came back, so long as the
1749 : * server didn't crash.
1750 : */
1751 0 : if (NT_STATUS_EQUAL(status,
1752 : NT_STATUS_CONNECTION_DISCONNECTED)) {
1753 0 : printf("cli_setpathinfo info %x (%s) of %s failed"
1754 : "error NT_STATUS_CONNECTION_DISCONNECTED\n",
1755 0 : (unsigned int)posix_smb1_setpath_array[i].level,
1756 : posix_smb1_setpath_array[i].name,
1757 : fname);
1758 0 : return status;
1759 : }
1760 :
1761 0 : printf("cli_setpathinfo info %x (%s) of %s got %s "
1762 : "(this is not an error)\n",
1763 0 : (unsigned int)posix_smb1_setpath_array[i].level,
1764 : posix_smb1_setpath_array[i].name,
1765 : fname,
1766 : nt_errstr(status));
1767 :
1768 0 : return NT_STATUS_OK;
1769 : }
1770 :
1771 : /*
1772 : Ensure we can call SMB1 setpathinfo in a symlink,
1773 : pointing to a real object or dangling. We mostly
1774 : expect errors, but the server must not crash.
1775 : */
1776 0 : bool run_posix_symlink_setpathinfo_test(int dummy)
1777 : {
1778 0 : TALLOC_CTX *frame = NULL;
1779 0 : struct cli_state *cli_unix = NULL;
1780 : NTSTATUS status;
1781 0 : uint16_t fnum = (uint16_t)-1;
1782 0 : const char *fname_real = "file_setpath_real";
1783 0 : const char *fname_real_symlink = "file_real_setpath_symlink";
1784 0 : const char *nonexist = "nonexist_setpath";
1785 0 : const char *nonexist_symlink = "dangling_setpath_symlink";
1786 0 : bool correct = false;
1787 : size_t i;
1788 :
1789 0 : frame = talloc_stackframe();
1790 :
1791 0 : printf("Starting POSIX-SYMLINK-SETPATHINFO test\n");
1792 :
1793 0 : if (!torture_open_connection(&cli_unix, 0)) {
1794 0 : TALLOC_FREE(frame);
1795 0 : return false;
1796 : }
1797 :
1798 0 : torture_conn_set_sockopt(cli_unix);
1799 :
1800 0 : status = torture_setup_unix_extensions(cli_unix);
1801 0 : if (!NT_STATUS_IS_OK(status)) {
1802 0 : TALLOC_FREE(frame);
1803 0 : return false;
1804 : }
1805 :
1806 : /* Start with a clean slate. */
1807 0 : cli_posix_unlink(cli_unix, fname_real);
1808 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1809 0 : cli_posix_unlink(cli_unix, nonexist);
1810 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1811 :
1812 : /* Create a real file. */
1813 0 : status = cli_posix_open(cli_unix,
1814 : fname_real,
1815 : O_RDWR|O_CREAT,
1816 : 0644,
1817 : &fnum);
1818 0 : if (!NT_STATUS_IS_OK(status)) {
1819 0 : printf("cli_posix_open of %s failed error %s\n",
1820 : fname_real,
1821 : nt_errstr(status));
1822 0 : goto out;
1823 : }
1824 0 : status = cli_close(cli_unix, fnum);
1825 0 : if (!NT_STATUS_IS_OK(status)) {
1826 0 : printf("cli_close failed %s\n", nt_errstr(status));
1827 0 : goto out;
1828 : }
1829 0 : fnum = (uint16_t)-1;
1830 :
1831 : /* Create symlink to real target. */
1832 0 : status = cli_posix_symlink(cli_unix,
1833 : fname_real,
1834 : fname_real_symlink);
1835 0 : if (!NT_STATUS_IS_OK(status)) {
1836 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1837 : fname_real_symlink,
1838 : fname_real,
1839 : nt_errstr(status));
1840 0 : goto out;
1841 : }
1842 :
1843 : /* Now create symlink to non-existing target. */
1844 0 : status = cli_posix_symlink(cli_unix,
1845 : nonexist,
1846 : nonexist_symlink);
1847 0 : if (!NT_STATUS_IS_OK(status)) {
1848 0 : printf("cli_posix_symlink of %s -> %s failed error %s\n",
1849 : nonexist_symlink,
1850 : nonexist,
1851 : nt_errstr(status));
1852 0 : goto out;
1853 : }
1854 :
1855 0 : for (i = 0; i < ARRAY_SIZE(posix_smb1_setpath_array); i++) {
1856 0 : status = do_setpath(frame,
1857 : cli_unix,
1858 : fname_real_symlink,
1859 : i);
1860 0 : if (!NT_STATUS_IS_OK(status)) {
1861 0 : goto out;
1862 : }
1863 0 : status = do_setpath(frame,
1864 : cli_unix,
1865 : nonexist_symlink,
1866 : i);
1867 0 : if (!NT_STATUS_IS_OK(status)) {
1868 0 : goto out;
1869 : }
1870 : }
1871 :
1872 0 : printf("POSIX-SYMLINK-SETPATHINFO test passed\n");
1873 0 : correct = true;
1874 :
1875 0 : out:
1876 0 : if (fnum != (uint16_t)-1) {
1877 0 : cli_close(cli_unix, fnum);
1878 : }
1879 0 : cli_posix_unlink(cli_unix, fname_real);
1880 0 : cli_posix_unlink(cli_unix, fname_real_symlink);
1881 0 : cli_posix_unlink(cli_unix, nonexist);
1882 0 : cli_posix_unlink(cli_unix, nonexist_symlink);
1883 :
1884 0 : if (!torture_close_connection(cli_unix)) {
1885 0 : correct = false;
1886 : }
1887 :
1888 0 : TALLOC_FREE(frame);
1889 0 : return correct;
1890 : }
|