LCOV - code coverage report
Current view: top level - source3/torture - test_posix.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 657 917 71.6 %
Date: 2024-04-21 15:09:00 Functions: 15 15 100.0 %

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

Generated by: LCOV version 1.14