LCOV - code coverage report
Current view: top level - source3/torture - test_smb1_dfs.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 587 1610 36.5 %
Date: 2024-02-29 22:57:05 Functions: 33 72 45.8 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB1 DFS tests.
       4             :    Copyright (C) Jeremy Allison 2022.
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "torture/proto.h"
      22             : #include "client.h"
      23             : #include "trans2.h"
      24             : #include "../libcli/smb/smbXcli_base.h"
      25             : #include "libcli/security/security.h"
      26             : #include "libsmb/proto.h"
      27             : #include "auth/credentials/credentials.h"
      28             : #include "auth/gensec/gensec.h"
      29             : #include "auth_generic.h"
      30             : #include "../librpc/ndr/libndr.h"
      31             : #include "libsmb/clirap.h"
      32             : #include "async_smb.h"
      33             : #include "../lib/util/tevent_ntstatus.h"
      34             : #include "lib/util/time_basic.h"
      35             : 
      36             : extern fstring host, workgroup, share, password, username, myname;
      37             : extern struct cli_credentials *torture_creds;
      38             : 
      39             : /*
      40             :  * Open an SMB1 file readonly and return the create time.
      41             :  */
      42          38 : static NTSTATUS get_smb1_crtime(struct cli_state *cli,
      43             :                                 const char *pathname,
      44             :                                 struct timespec *pcrtime)
      45             : {
      46           0 :         NTSTATUS status;
      47          38 :         uint16_t fnum = 0;
      48          38 :         struct timespec crtime = {0};
      49             : 
      50             :         /*
      51             :          * Open the file.
      52             :          */
      53             : 
      54          38 :         status = smb1cli_ntcreatex(cli->conn,
      55          38 :                                    cli->timeout,
      56             :                                    cli->smb1.pid,
      57             :                                    cli->smb1.tcon,
      58             :                                    cli->smb1.session,
      59             :                                    pathname,
      60             :                                    OPLOCK_NONE, /* CreatFlags */
      61             :                                    0, /* RootDirectoryFid */
      62             :                                    SEC_STD_SYNCHRONIZE|
      63             :                                         SEC_FILE_READ_DATA|
      64             :                                         SEC_FILE_READ_ATTRIBUTE, /* DesiredAccess */
      65             :                                    0, /* AllocationSize */
      66             :                                    FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
      67             :                                    FILE_SHARE_READ|
      68             :                                         FILE_SHARE_WRITE|
      69             :                                         FILE_SHARE_DELETE, /* ShareAccess */
      70             :                                    FILE_OPEN, /* CreateDisposition */
      71             :                                    0, /* CreateOptions */
      72             :                                    2, /* ImpersonationLevel */
      73             :                                    0, /* SecurityFlags */
      74             :                                    &fnum);
      75          38 :         if (!NT_STATUS_IS_OK(status)) {
      76           6 :                 return status;
      77             :         }
      78             : 
      79             :         /*
      80             :          * Get the create time. Note - we can use
      81             :          * a higher-level cli_XXX function here
      82             :          * for SMB1 as cli_qfileinfo_basic()
      83             :          * doesn't use any pathnames, only fnums
      84             :          * so it isn't affected by DFS pathnames.
      85             :          */
      86          32 :         status = cli_qfileinfo_basic(cli,
      87             :                                      fnum,
      88             :                                      NULL, /* attr */
      89             :                                      NULL, /* size */
      90             :                                      &crtime, /* create_time */
      91             :                                      NULL, /* access_time */
      92             :                                      NULL, /* write_time */
      93             :                                      NULL, /* change_time */
      94             :                                      NULL);
      95          32 :         if (NT_STATUS_IS_OK(status)) {
      96          32 :                 *pcrtime = crtime;
      97             :         }
      98             : 
      99          32 :         (void)smb1cli_close(cli->conn,
     100          32 :                             cli->timeout,
     101             :                             cli->smb1.pid,
     102             :                             cli->smb1.tcon,
     103             :                             cli->smb1.session,
     104             :                             fnum,
     105             :                             0); /* last_modified */
     106          32 :         return status;
     107             : }
     108             : 
     109             : /*
     110             :  * Check a crtime matches a given SMB1 path.
     111             :  */
     112          30 : static bool smb1_crtime_matches(struct cli_state *cli,
     113             :                                 const char *match_pathname,
     114             :                                 struct timespec crtime_tomatch,
     115             :                                 const char *test_pathname)
     116             : {
     117          30 :         struct timespec test_crtime = { 0 };
     118           0 :         NTSTATUS status;
     119          30 :         bool equal = false;
     120             : 
     121          30 :         status = get_smb1_crtime(cli,
     122             :                                 test_pathname,
     123             :                                 &test_crtime);
     124          30 :         if (!NT_STATUS_IS_OK(status)) {
     125           2 :                 printf("%s: Failed to get crtime "
     126             :                         "for %s, (%s)\n",
     127             :                         __func__,
     128             :                         test_pathname,
     129             :                         nt_errstr(status));
     130           2 :                 return false;
     131             :         }
     132          28 :         equal = (timespec_compare(&test_crtime, &crtime_tomatch) == 0);
     133          28 :         if (!equal) {
     134           0 :                 struct timeval_buf test_buf;
     135           0 :                 struct timeval_buf tomatch_buf;
     136           0 :                 printf("%s: crtime mismatch "
     137             :                         "%s:crtime_tomatch=%s, %s:test_crtime = %s\n",
     138             :                         __func__,
     139             :                         match_pathname,
     140             :                         timespec_string_buf(&crtime_tomatch,
     141             :                                 true,
     142             :                                 &tomatch_buf),
     143             :                         test_pathname,
     144             :                         timespec_string_buf(&test_crtime,
     145             :                                 true,
     146             :                                 &test_buf));
     147           0 :                 return false;
     148             :         }
     149          28 :         return true;
     150             : }
     151             : 
     152             : /*
     153             :  * Delete an SMB1 file on a DFS share.
     154             :  */
     155          50 : static NTSTATUS smb1_dfs_delete(struct cli_state *cli,
     156             :                                 const char *pathname)
     157             : {
     158           0 :         NTSTATUS status;
     159          50 :         uint16_t fnum = 0;
     160             : 
     161             :         /*
     162             :          * Open the file.
     163             :          */
     164             : 
     165          50 :         status = smb1cli_ntcreatex(cli->conn,
     166          50 :                                    cli->timeout,
     167             :                                    cli->smb1.pid,
     168             :                                    cli->smb1.tcon,
     169             :                                    cli->smb1.session,
     170             :                                    pathname,
     171             :                                    OPLOCK_NONE, /* CreatFlags */
     172             :                                    0, /* RootDirectoryFid */
     173             :                                    SEC_STD_SYNCHRONIZE|
     174             :                                         SEC_STD_DELETE, /* DesiredAccess */
     175             :                                    0, /* AllocationSize */
     176             :                                    FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
     177             :                                    FILE_SHARE_READ|
     178             :                                         FILE_SHARE_WRITE|
     179             :                                         FILE_SHARE_DELETE, /* ShareAccess */
     180             :                                    FILE_OPEN, /* CreateDisposition */
     181             :                                    0, /* CreateOptions */
     182             :                                    2, /* ImpersonationLevel */
     183             :                                    0, /* SecurityFlags */
     184             :                                    &fnum);
     185          50 :         if (!NT_STATUS_IS_OK(status)) {
     186          38 :                 return status;
     187             :         }
     188             : 
     189             :         /*
     190             :          * Set delete on close. Note - we can use
     191             :          * a higher-level cli_XXX function here
     192             :          * for SMB1 as cli_nt_delete_on_close()
     193             :          * doesn't use any pathnames, only fnums
     194             :          * so it isn't affected by DFS pathnames.
     195             :          */
     196             :         /*
     197             :          */
     198          12 :         status = cli_nt_delete_on_close(cli, fnum, 1);
     199          12 :         if (!NT_STATUS_IS_OK(status)) {
     200           0 :                 return status;
     201             :         }
     202          12 :         return smb1cli_close(cli->conn,
     203          12 :                             cli->timeout,
     204             :                             cli->smb1.pid,
     205             :                             cli->smb1.tcon,
     206             :                             cli->smb1.session,
     207             :                             fnum,
     208             :                             0); /* last_modified */
     209             : }
     210             : 
     211             : static void smb1_mv_done(struct tevent_req *subreq);
     212             : 
     213             : struct smb1_mv_state {
     214             :         uint16_t vwv[1];
     215             : };
     216             : 
     217           0 : static struct tevent_req *smb1_mv_send(TALLOC_CTX *mem_ctx,
     218             :                                        struct tevent_context *ev,
     219             :                                        struct cli_state *cli,
     220             :                                        const char *src_dfs_name,
     221             :                                        const char *target_name)
     222             : {
     223           0 :         uint8_t *bytes = NULL;
     224           0 :         struct tevent_req *req = NULL;
     225           0 :         struct tevent_req *subreq = NULL;
     226           0 :         struct smb1_mv_state *state = NULL;
     227             : 
     228           0 :         req = tevent_req_create(mem_ctx,
     229             :                                 &state,
     230             :                                 struct smb1_mv_state);
     231           0 :         if (req == NULL) {
     232           0 :                 return NULL;
     233             :         }
     234             : 
     235           0 :         PUSH_LE_U16(state->vwv,
     236             :                     0,
     237             :                     FILE_ATTRIBUTE_SYSTEM |
     238             :                     FILE_ATTRIBUTE_HIDDEN |
     239             :                     FILE_ATTRIBUTE_DIRECTORY);
     240             : 
     241           0 :         bytes = talloc_array(state, uint8_t, 1);
     242           0 :         if (tevent_req_nomem(bytes, req)) {
     243           0 :                 return tevent_req_post(req, ev);
     244             :         }
     245           0 :         bytes[0] = 4;
     246           0 :         bytes = smb_bytes_push_str(bytes,
     247           0 :                                    smbXcli_conn_use_unicode(cli->conn),
     248             :                                    src_dfs_name,
     249           0 :                                    strlen(src_dfs_name)+1,
     250             :                                    NULL);
     251           0 :         if (tevent_req_nomem(bytes, req)) {
     252           0 :                 return tevent_req_post(req, ev);
     253             :         }
     254             : 
     255           0 :         bytes = talloc_realloc(state,
     256             :                                bytes,
     257             :                                uint8_t,
     258             :                                talloc_get_size(bytes)+1);
     259           0 :         if (tevent_req_nomem(bytes, req)) {
     260           0 :                 return tevent_req_post(req, ev);
     261             :         }
     262             : 
     263           0 :         bytes[talloc_get_size(bytes)-1] = 4;
     264           0 :         bytes = smb_bytes_push_str(bytes,
     265           0 :                                    smbXcli_conn_use_unicode(cli->conn),
     266             :                                    target_name,
     267           0 :                                    strlen(target_name)+1,
     268             :                                    NULL);
     269           0 :         if (tevent_req_nomem(bytes, req)) {
     270           0 :                 return tevent_req_post(req, ev);
     271             :         }
     272             : 
     273           0 :         subreq = cli_smb_send(state,
     274             :                               ev,
     275             :                               cli,
     276             :                               SMBmv,
     277             :                               0, /* additional_flags */
     278             :                               0, /* additional_flags2 */
     279             :                               1,
     280           0 :                               state->vwv,
     281           0 :                               talloc_get_size(bytes),
     282             :                               bytes);
     283           0 :         if (tevent_req_nomem(subreq, req)) {
     284           0 :                 return tevent_req_post(req, ev);
     285             :         }
     286           0 :         tevent_req_set_callback(subreq, smb1_mv_done, req);
     287           0 :         return req;
     288             : }
     289             : 
     290           0 : static void smb1_mv_done(struct tevent_req *subreq)
     291             : {
     292           0 :         NTSTATUS status = cli_smb_recv(subreq,
     293             :                                        NULL,
     294             :                                        NULL,
     295             :                                        0,
     296             :                                        NULL,
     297             :                                        NULL,
     298             :                                        NULL,
     299             :                                        NULL);
     300           0 :         tevent_req_simple_finish_ntstatus(subreq,
     301             :                                           status);
     302           0 : }
     303             : 
     304           0 : static NTSTATUS smb1_mv_recv(struct tevent_req *req)
     305             : {
     306           0 :         return tevent_req_simple_recv_ntstatus(req);
     307             : }
     308             : 
     309             : /*
     310             :  * Rename an SMB1 file on a DFS share. SMBmv version.
     311             :  */
     312           0 : static NTSTATUS smb1_mv(struct cli_state *cli,
     313             :                         const char *src_dfs_name,
     314             :                         const char *target_name)
     315             : {
     316           0 :         TALLOC_CTX *frame = NULL;
     317           0 :         struct tevent_context *ev;
     318           0 :         struct tevent_req *req;
     319           0 :         NTSTATUS status;
     320             : 
     321           0 :         frame = talloc_stackframe();
     322             : 
     323           0 :         ev = samba_tevent_context_init(frame);
     324           0 :         if (ev == NULL) {
     325           0 :                 status = NT_STATUS_NO_MEMORY;
     326           0 :                 goto fail;
     327             :         }
     328             : 
     329           0 :         req = smb1_mv_send(frame,
     330             :                            ev,
     331             :                            cli,
     332             :                            src_dfs_name,
     333             :                            target_name);
     334           0 :         if (req == NULL) {
     335           0 :                 status = NT_STATUS_NO_MEMORY;
     336           0 :                 goto fail;
     337             :         }
     338             : 
     339           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     340           0 :                 goto fail;
     341             :         }
     342             : 
     343           0 :         status = smb1_mv_recv(req);
     344             : 
     345           0 :   fail:
     346             : 
     347           0 :         TALLOC_FREE(frame);
     348           0 :         return status;
     349             : }
     350             : 
     351           0 : static bool test_smb1_mv(struct cli_state *cli,
     352             :                          const char *src_dfs_name)
     353             : {
     354           0 :         struct timespec test_timespec = { 0 };
     355           0 :         NTSTATUS status;
     356             : 
     357           0 :         status = smb1_mv(cli,
     358             :                          src_dfs_name,
     359             :                          "BAD\\BAD\\renamed_file");
     360           0 :         if (!NT_STATUS_IS_OK(status)) {
     361           0 :                 printf("%s:%d SMBmv of %s -> %s should succeed "
     362             :                         "got %s\n",
     363             :                         __FILE__,
     364             :                         __LINE__,
     365             :                         src_dfs_name,
     366             :                         "BAD\\BAD\\renamed_file",
     367             :                         nt_errstr(status));
     368           0 :                 return false;
     369             :         }
     370             : 
     371             :         /* Ensure we did rename. */
     372           0 :         status = get_smb1_crtime(cli,
     373             :                                 "BAD\\BAD\\renamed_file",
     374             :                                 &test_timespec);
     375           0 :         if (!NT_STATUS_IS_OK(status)) {
     376           0 :                 printf("%s:%d Failed to get crtime "
     377             :                         "for %s, (%s)\n",
     378             :                         __FILE__,
     379             :                         __LINE__,
     380             :                         "BAD\\BAD\\renamed_file",
     381             :                         nt_errstr(status));
     382           0 :                 return false;
     383             :         }
     384             : 
     385             :         /* Put it back. */
     386           0 :         status = smb1_mv(cli,
     387             :                          "BAD\\BAD\\renamed_file",
     388             :                          src_dfs_name);
     389           0 :         if (!NT_STATUS_IS_OK(status)) {
     390           0 :                 printf("%s:%d SMBmv of %s -> %s should succeed "
     391             :                         "got %s\n",
     392             :                         __FILE__,
     393             :                         __LINE__,
     394             :                         "BAD\\BAD\\renamed_file",
     395             :                         src_dfs_name,
     396             :                         nt_errstr(status));
     397           0 :                 return false;
     398             :         }
     399             : 
     400             :         /* Ensure we did put it back. */
     401           0 :         status = get_smb1_crtime(cli,
     402             :                                 src_dfs_name,
     403             :                                 &test_timespec);
     404           0 :         if (!NT_STATUS_IS_OK(status)) {
     405           0 :                 printf("%s:%d Failed to get crtime "
     406             :                         "for %s, (%s)\n",
     407             :                         __FILE__,
     408             :                         __LINE__,
     409             :                         src_dfs_name,
     410             :                         nt_errstr(status));
     411           0 :                 return false;
     412             :         }
     413             : 
     414             :         /* Try with a non-DFS name. */
     415           0 :         status = smb1_mv(cli,
     416             :                          src_dfs_name,
     417             :                          "renamed_file");
     418           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
     419             :                 /* Fails I think as target becomes "" on server. */
     420           0 :                 printf("%s:%d SMBmv of %s -> %s should get "
     421             :                         "NT_STATUS_OBJECT_PATH_SYNTAX_BAD got %s\n",
     422             :                         __FILE__,
     423             :                         __LINE__,
     424             :                         src_dfs_name,
     425             :                         "renamed_file",
     426             :                         nt_errstr(status));
     427           0 :                 return false;
     428             :         }
     429             : 
     430             :         /* Try with a non-DFS name. */
     431           0 :         status = smb1_mv(cli,
     432             :                          src_dfs_name,
     433             :                          "BAD\\renamed_file");
     434           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
     435             :                 /* Fails I think as target becomes "" on server. */
     436           0 :                 printf("%s:%d SMBmv of %s -> %s should get "
     437             :                         "NT_STATUS_OBJECT_PATH_SYNTAX_BAD got %s\n",
     438             :                         __FILE__,
     439             :                         __LINE__,
     440             :                         src_dfs_name,
     441             :                         "BAD\\renamed_file",
     442             :                         nt_errstr(status));
     443           0 :                 return false;
     444             :         }
     445           0 :         return true;
     446             : }
     447             : 
     448             : static void smb1_setpathinfo_done(struct tevent_req *subreq);
     449             : 
     450             : struct smb1_setpathinfo_state {
     451             :         uint16_t setup;
     452             :         uint8_t *param;
     453             :         uint8_t *data;
     454             : };
     455             : 
     456           0 : static struct tevent_req *smb1_setpathinfo_send(TALLOC_CTX *mem_ctx,
     457             :                                                 struct tevent_context *ev,
     458             :                                                 struct cli_state *cli,
     459             :                                                 const char *src_dfs_name,
     460             :                                                 const char *target_name,
     461             :                                                 uint16_t info_level)
     462             : {
     463           0 :         struct tevent_req *req = NULL;
     464           0 :         struct tevent_req *subreq = NULL;
     465           0 :         struct smb1_setpathinfo_state *state = NULL;
     466           0 :         smb_ucs2_t *converted_str = NULL;
     467           0 :         size_t converted_size_bytes = 0;
     468           0 :         bool ok = false;
     469             : 
     470           0 :         req = tevent_req_create(mem_ctx,
     471             :                                 &state,
     472             :                                 struct smb1_setpathinfo_state);
     473           0 :         if (req == NULL) {
     474           0 :                 return NULL;
     475             :         }
     476             : 
     477           0 :         PUSH_LE_U16(&state->setup, 0, TRANSACT2_SETPATHINFO);
     478             : 
     479           0 :         state->param = talloc_zero_array(state, uint8_t, 6);
     480           0 :         if (tevent_req_nomem(state->param, req)) {
     481           0 :                 return tevent_req_post(req, ev);
     482             :         }
     483           0 :         PUSH_LE_U16(state->param, 0, info_level);
     484             : 
     485           0 :         state->param = trans2_bytes_push_str(state->param,
     486           0 :                                              smbXcli_conn_use_unicode(cli->conn),
     487             :                                              src_dfs_name,
     488           0 :                                              strlen(src_dfs_name)+1,
     489             :                                              NULL);
     490           0 :         if (tevent_req_nomem(state->param, req)) {
     491           0 :                 return tevent_req_post(req, ev);
     492             :         }
     493             : 
     494           0 :         ok = push_ucs2_talloc(state,
     495             :                               &converted_str,
     496             :                               target_name,
     497             :                               &converted_size_bytes);
     498           0 :         if (!ok) {
     499           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     500           0 :                 return tevent_req_post(req, ev);
     501             :         }
     502             : 
     503             :         /*
     504             :          * W2K8 insists the dest name is not null
     505             :          * terminated. Remove the last 2 zero bytes
     506             :          * and reduce the name length.
     507             :          */
     508             : 
     509           0 :         if (converted_size_bytes < 2) {
     510           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     511           0 :                 return tevent_req_post(req, ev);
     512             :         }
     513           0 :         converted_size_bytes -= 2;
     514             : 
     515           0 :         state->data = talloc_zero_array(state,
     516             :                                         uint8_t,
     517             :                                         12 + converted_size_bytes);
     518           0 :         if (tevent_req_nomem(state->data, req)) {
     519           0 :                 return tevent_req_post(req, ev);
     520             :         }
     521             : 
     522           0 :         SIVAL(state->data, 8, converted_size_bytes);
     523           0 :         memcpy(state->data + 12, converted_str, converted_size_bytes);
     524             : 
     525           0 :         subreq = cli_trans_send(state, /* mem ctx. */
     526             :                                 ev,/* event ctx. */
     527             :                                 cli,/* cli_state. */
     528             :                                 0,/* additional_flags2 */
     529             :                                 SMBtrans2,              /* cmd. */
     530             :                                 NULL,/* pipe name. */
     531             :                                 -1,/* fid. */
     532             :                                 0,/* function. */
     533             :                                 0,/* flags. */
     534           0 :                                 &state->setup,/* setup. */
     535             :                                 1,/* num setup uint16_t words. */
     536             :                                 0,/* max returned setup. */
     537           0 :                                 state->param,/* param. */
     538           0 :                                 talloc_get_size(state->param),/* num param. */
     539             :                                 2,/* max returned param. */
     540           0 :                                 state->data,/* data. */
     541           0 :                                 talloc_get_size(state->data),/* num data. */
     542             :                                 0);/* max returned data. */
     543             : 
     544           0 :         if (tevent_req_nomem(subreq, req)) {
     545           0 :                 return tevent_req_post(req, ev);
     546             :         }
     547           0 :         tevent_req_set_callback(subreq, smb1_setpathinfo_done, req);
     548           0 :         return req;
     549             : }
     550             : 
     551           0 : static void smb1_setpathinfo_done(struct tevent_req *subreq)
     552             : {
     553           0 :         NTSTATUS status = cli_trans_recv(subreq,
     554             :                                          NULL,
     555             :                                          NULL,
     556             :                                          NULL,
     557             :                                          0,
     558             :                                          NULL,
     559             :                                          NULL,
     560             :                                          0,
     561             :                                          NULL,
     562             :                                          NULL,
     563             :                                          0,
     564             :                                          NULL);
     565           0 :         tevent_req_simple_finish_ntstatus(subreq,
     566             :                                           status);
     567           0 : }
     568             : 
     569           0 : static NTSTATUS smb1_setpathinfo_recv(struct tevent_req *req)
     570             : {
     571           0 :         return tevent_req_simple_recv_ntstatus(req);
     572             : }
     573             : 
     574             : /*
     575             :  * Rename or hardlink an SMB1 file on a DFS share. SMB1 setpathinfo
     576             :  * (pathnames only) version.
     577             :  */
     578           0 : static NTSTATUS smb1_setpathinfo(struct cli_state *cli,
     579             :                                  const char *src_dfs_name,
     580             :                                  const char *target_name,
     581             :                                  uint16_t info_level)
     582             : {
     583           0 :         TALLOC_CTX *frame = NULL;
     584           0 :         struct tevent_context *ev;
     585           0 :         struct tevent_req *req;
     586           0 :         NTSTATUS status;
     587             : 
     588           0 :         frame = talloc_stackframe();
     589             : 
     590           0 :         ev = samba_tevent_context_init(frame);
     591           0 :         if (ev == NULL) {
     592           0 :                 status = NT_STATUS_NO_MEMORY;
     593           0 :                 goto fail;
     594             :         }
     595             : 
     596           0 :         req = smb1_setpathinfo_send(frame,
     597             :                                     ev,
     598             :                                     cli,
     599             :                                     src_dfs_name,
     600             :                                     target_name,
     601             :                                     info_level);
     602           0 :         if (req == NULL) {
     603           0 :                 status = NT_STATUS_NO_MEMORY;
     604           0 :                 goto fail;
     605             :         }
     606             : 
     607           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     608           0 :                 goto fail;
     609             :         }
     610             : 
     611           0 :         status = smb1_setpathinfo_recv(req);
     612             : 
     613           0 :   fail:
     614             : 
     615           0 :         TALLOC_FREE(frame);
     616           0 :         return status;
     617             : }
     618             : 
     619           0 : static NTSTATUS smb1_setpathinfo_rename(struct cli_state *cli,
     620             :                                         const char *src_dfs_name,
     621             :                                         const char *target_name)
     622             : {
     623           0 :         return smb1_setpathinfo(cli,
     624             :                                 src_dfs_name,
     625             :                                 target_name,
     626             :                                 SMB_FILE_RENAME_INFORMATION);
     627             : }
     628             : 
     629           0 : static bool test_smb1_setpathinfo_rename(struct cli_state *cli,
     630             :                                          const char *src_dfs_name)
     631             : {
     632           0 :         struct timespec test_crtime = { 0 };
     633           0 :         NTSTATUS status;
     634           0 :         const char *putback_path = NULL;
     635             : 
     636             :         /*
     637             :          * On Windows, setpathinfo rename where the target contains
     638             :          * any directory separator returns STATUS_NOT_SUPPORTED.
     639             :          *
     640             :          * MS-SMB behavior note: <133> Section 3.3.5.10.6:
     641             :          *
     642             :          * "If the file name pointed to by the FileName parameter of the
     643             :          * FILE_RENAME_INFORMATION structure contains a separator character,
     644             :          * then the request fails with STATUS_NOT_SUPPORTED."
     645             :          */
     646           0 :         status = smb1_setpathinfo_rename(cli,
     647             :                                          src_dfs_name,
     648             :                                          "BAD\\BAD\\renamed_file");
     649           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
     650           0 :                 printf("%s:%d SMB1 setpathinfo rename of %s -> %s should get "
     651             :                         "NT_STATUS_NOT_SUPPORTED got %s\n",
     652             :                         __FILE__,
     653             :                         __LINE__,
     654             :                         src_dfs_name,
     655             :                         "BAD\\BAD\\renamed_file",
     656             :                         nt_errstr(status));
     657           0 :                 return false;
     658             :         }
     659             : 
     660             :         /* Try with a non-DFS name. */
     661           0 :         status = smb1_setpathinfo_rename(cli,
     662             :                                          src_dfs_name,
     663             :                                          "renamed_file");
     664           0 :         if (!NT_STATUS_IS_OK(status)) {
     665           0 :                 printf("%s:%d SMB1 setpathinfo rename of %s -> %s "
     666             :                         "should succeed got %s\n",
     667             :                         __FILE__,
     668             :                         __LINE__,
     669             :                         src_dfs_name,
     670             :                         "renamed_file",
     671             :                         nt_errstr(status));
     672           0 :                 return false;
     673             :         }
     674             : 
     675             :         /* Ensure we did rename. */
     676           0 :         status = get_smb1_crtime(cli,
     677             :                                 "BAD\\BAD\\renamed_file",
     678             :                                 &test_crtime);
     679           0 :         if (!NT_STATUS_IS_OK(status)) {
     680           0 :                 printf("%s:%d Failed to get crtime "
     681             :                         "for %s, (%s)\n",
     682             :                         __FILE__,
     683             :                         __LINE__,
     684             :                         "BAD\\BAD\\renamed_file",
     685             :                         nt_errstr(status));
     686           0 :                 return false;
     687             :         }
     688             : 
     689             :         /*
     690             :          * To put it back we need to reverse the DFS-ness of src
     691             :          * and destination paths.
     692             :          */
     693           0 :         putback_path = strrchr(src_dfs_name, '\\');
     694           0 :         if (putback_path == NULL) {
     695           0 :                 printf("%s:%d non DFS path %s passed. Internal error\n",
     696             :                         __FILE__,
     697             :                         __LINE__,
     698             :                         src_dfs_name);
     699           0 :                 return false;
     700             :         }
     701             :         /* Walk past the last '\\' */
     702           0 :         putback_path++;
     703             : 
     704             :         /* Put it back. */
     705           0 :         status = smb1_setpathinfo_rename(cli,
     706             :                                          "BAD\\BAD\\renamed_file",
     707             :                                          putback_path);
     708           0 :         if (!NT_STATUS_IS_OK(status)) {
     709           0 :                 printf("%s:%d SMB1 setpathinfo rename of %s -> %s "
     710             :                         "should succeed got %s\n",
     711             :                         __FILE__,
     712             :                         __LINE__,
     713             :                         "BAD\\BAD\\renamed_file",
     714             :                         putback_path,
     715             :                         nt_errstr(status));
     716           0 :                 return false;
     717             :         }
     718             : 
     719             :         /* Ensure we did rename. */
     720           0 :         status = get_smb1_crtime(cli,
     721             :                                 src_dfs_name,
     722             :                                 &test_crtime);
     723           0 :         if (!NT_STATUS_IS_OK(status)) {
     724           0 :                 printf("%s:%d Failed to get crtime "
     725             :                         "for %s, (%s)\n",
     726             :                         __FILE__,
     727             :                         __LINE__,
     728             :                         src_dfs_name,
     729             :                         nt_errstr(status));
     730           0 :                 return false;
     731             :         }
     732             : 
     733           0 :         return true;
     734             : }
     735             : 
     736           0 : static NTSTATUS smb1_setpathinfo_hardlink(struct cli_state *cli,
     737             :                                           const char *src_dfs_name,
     738             :                                           const char *target_name)
     739             : {
     740           0 :         return smb1_setpathinfo(cli,
     741             :                                 src_dfs_name,
     742             :                                 target_name,
     743             :                                 SMB_FILE_LINK_INFORMATION);
     744             : }
     745             : 
     746           0 : static bool test_smb1_setpathinfo_hardlink(struct cli_state *cli,
     747             :                                            const char *src_dfs_name)
     748             : {
     749           0 :         NTSTATUS status;
     750             : 
     751             :         /*
     752             :          * On Windows, setpathinfo rename where the target contains
     753             :          * any directory separator returns STATUS_NOT_SUPPORTED.
     754             :          *
     755             :          * MS-SMB behavior note: <133> Section 3.3.5.10.6:
     756             :          *
     757             :          * "If the file name pointed to by the FileName parameter of the
     758             :          * FILE_RENAME_INFORMATION structure contains a separator character,
     759             :          * then the request fails with STATUS_NOT_SUPPORTED."
     760             :          *
     761             :          * setpathinfo info level SMB_FILE_LINK_INFORMATION
     762             :          * seems to do the same, but this could be an artifact
     763             :          * of the Windows version tested (Win2K8). I will
     764             :          * revisit this when I'm able to test against
     765             :          * a later Windows version with a DFS server.
     766             :          */
     767           0 :         status = smb1_setpathinfo_hardlink(cli,
     768             :                                          src_dfs_name,
     769             :                                          "BAD\\BAD\\hlink");
     770           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
     771           0 :                 printf("%s:%d SMB1 setpathinfo hardlink of %s -> %s should get "
     772             :                         "NT_STATUS_NOT_SUPPORTED got %s\n",
     773             :                         __FILE__,
     774             :                         __LINE__,
     775             :                         src_dfs_name,
     776             :                         "BAD\\BAD\\hlink",
     777             :                         nt_errstr(status));
     778           0 :                 return false;
     779             :         }
     780             : 
     781             :         /* Try with a non-DFS name. */
     782             :         /*
     783             :          * At least on Windows 2008 this also fails with
     784             :          * NT_STATUS_NOT_SUPPORTED, leading me to believe
     785             :          * setting hardlinks is only supported via NTrename
     786             :          * in SMB1.
     787             :          */
     788           0 :         status = smb1_setpathinfo_hardlink(cli,
     789             :                                            src_dfs_name,
     790             :                                            "hlink");
     791           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
     792           0 :                 printf("%s:%d SMB1 setpathinfo hardlink of %s -> %s should get "
     793             :                         "NT_STATUS_NOT_SUPPORTED got %s\n",
     794             :                         __FILE__,
     795             :                         __LINE__,
     796             :                         src_dfs_name,
     797             :                         "hlink",
     798             :                         nt_errstr(status));
     799           0 :                 return false;
     800             :         }
     801           0 :         return true;
     802             : }
     803             : 
     804             : static void smb1_ntrename_done(struct tevent_req *subreq);
     805             : 
     806             : struct smb1_ntrename_state {
     807             :         uint16_t vwv[4];
     808             : };
     809             : 
     810           0 : static struct tevent_req *smb1_ntrename_send(TALLOC_CTX *mem_ctx,
     811             :                                              struct tevent_context *ev,
     812             :                                              struct cli_state *cli,
     813             :                                              const char *src_dfs_name,
     814             :                                              const char *target_name,
     815             :                                              uint16_t rename_flag)
     816             : {
     817           0 :         struct tevent_req *req = NULL;
     818           0 :         struct tevent_req *subreq = NULL;
     819           0 :         struct smb1_ntrename_state *state = NULL;
     820           0 :         uint8_t *bytes = NULL;
     821             : 
     822           0 :         req = tevent_req_create(mem_ctx,
     823             :                                 &state,
     824             :                                 struct smb1_ntrename_state);
     825           0 :         if (req == NULL) {
     826           0 :                 return NULL;
     827             :         }
     828             : 
     829           0 :         PUSH_LE_U16(state->vwv,
     830             :                 0,
     831             :                 FILE_ATTRIBUTE_SYSTEM |
     832             :                         FILE_ATTRIBUTE_HIDDEN |
     833             :                         FILE_ATTRIBUTE_DIRECTORY);
     834           0 :         PUSH_LE_U16(state->vwv, 2, rename_flag);
     835             : 
     836           0 :         bytes = talloc_array(state, uint8_t, 1);
     837           0 :         if (tevent_req_nomem(bytes, req)) {
     838           0 :                 return tevent_req_post(req, ev);
     839             :         }
     840             : 
     841           0 :         bytes[0] = 4;
     842           0 :         bytes = smb_bytes_push_str(bytes,
     843           0 :                                    smbXcli_conn_use_unicode(cli->conn),
     844             :                                    src_dfs_name,
     845           0 :                                    strlen(src_dfs_name)+1,
     846             :                                    NULL);
     847           0 :         if (tevent_req_nomem(bytes, req)) {
     848           0 :                 return tevent_req_post(req, ev);
     849             :         }
     850           0 :         bytes = talloc_realloc(state,
     851             :                                bytes,
     852             :                                uint8_t,
     853             :                                talloc_get_size(bytes)+1);
     854           0 :         if (tevent_req_nomem(bytes, req)) {
     855           0 :                 return tevent_req_post(req, ev);
     856             :         }
     857             : 
     858           0 :         bytes[talloc_get_size(bytes)-1] = 4;
     859           0 :         bytes = smb_bytes_push_str(bytes,
     860           0 :                                    smbXcli_conn_use_unicode(cli->conn),
     861             :                                    target_name,
     862           0 :                                    strlen(target_name)+1,
     863             :                                    NULL);
     864           0 :         if (tevent_req_nomem(bytes, req)) {
     865           0 :                 return tevent_req_post(req, ev);
     866             :         }
     867             : 
     868           0 :         subreq = cli_smb_send(state,
     869             :                               ev,
     870             :                               cli,
     871             :                               SMBntrename,
     872             :                               0, /* additional_flags */
     873             :                               0, /* additional_flags2 */
     874             :                               4,
     875           0 :                               state->vwv,
     876           0 :                               talloc_get_size(bytes),
     877             :                               bytes);
     878           0 :         if (tevent_req_nomem(subreq, req)) {
     879           0 :                 return tevent_req_post(req, ev);
     880             :         }
     881           0 :         tevent_req_set_callback(subreq, smb1_ntrename_done, req);
     882           0 :         return req;
     883             : }
     884             : 
     885           0 : static void smb1_ntrename_done(struct tevent_req *subreq)
     886             : {
     887           0 :         NTSTATUS status = cli_smb_recv(subreq,
     888             :                                        NULL,
     889             :                                        NULL,
     890             :                                        0,
     891             :                                        NULL,
     892             :                                        NULL,
     893             :                                        NULL,
     894             :                                        NULL);
     895           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
     896           0 : }
     897             : 
     898           0 : static NTSTATUS smb1_ntrename_recv(struct tevent_req *req)
     899             : {
     900           0 :         return tevent_req_simple_recv_ntstatus(req);
     901             : }
     902             : 
     903             : /*
     904             :  * Rename or hardlink an SMB1 file on a DFS share. SMB1 ntrename version.
     905             :  * (pathnames only).
     906             :  */
     907           0 : static NTSTATUS smb1_ntrename(struct cli_state *cli,
     908             :                               const char *src_dfs_name,
     909             :                               const char *target_name,
     910             :                               uint16_t rename_flag)
     911             : {
     912           0 :         TALLOC_CTX *frame = NULL;
     913           0 :         struct tevent_context *ev;
     914           0 :         struct tevent_req *req;
     915           0 :         NTSTATUS status;
     916             : 
     917           0 :         frame = talloc_stackframe();
     918             : 
     919           0 :         ev = samba_tevent_context_init(frame);
     920           0 :         if (ev == NULL) {
     921           0 :                 status = NT_STATUS_NO_MEMORY;
     922           0 :                 goto fail;
     923             :         }
     924             : 
     925           0 :         req = smb1_ntrename_send(frame,
     926             :                                  ev,
     927             :                                  cli,
     928             :                                  src_dfs_name,
     929             :                                  target_name,
     930             :                                  rename_flag);
     931           0 :         if (req == NULL) {
     932           0 :                 status = NT_STATUS_NO_MEMORY;
     933           0 :                 goto fail;
     934             :         }
     935             : 
     936           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     937           0 :                 goto fail;
     938             :         }
     939             : 
     940           0 :         status = smb1_ntrename_recv(req);
     941             : 
     942           0 :   fail:
     943             : 
     944           0 :         TALLOC_FREE(frame);
     945           0 :         return status;
     946             : }
     947             : /*
     948             :  * Rename an SMB1 file on a DFS share. SMB1 ntrename version.
     949             :  */
     950           0 : static NTSTATUS smb1_ntrename_rename(struct cli_state *cli,
     951             :                                        const char *src_dfs_name,
     952             :                                        const char *target_name)
     953             : {
     954           0 :         return smb1_ntrename(cli,
     955             :                              src_dfs_name,
     956             :                              target_name,
     957             :                              RENAME_FLAG_RENAME);
     958             : }
     959             : 
     960             : 
     961           0 : static bool test_smb1_ntrename_rename(struct cli_state *cli,
     962             :                                       const char *src_dfs_name)
     963             : {
     964           0 :         struct timespec test_crtime = { 0 };
     965           0 :         NTSTATUS status;
     966             : 
     967             :         /* Try with a non-DFS name. */
     968           0 :         status = smb1_ntrename_rename(cli,
     969             :                                       src_dfs_name,
     970             :                                       "renamed_file");
     971           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
     972             :                 /* Fails I think as target becomes "" on server. */
     973           0 :                 printf("%s:%d SMB1 ntrename rename of %s -> %s should get "
     974             :                         "NT_STATUS_OBJECT_PATH_SYNTAX_BAD got %s\n",
     975             :                         __FILE__,
     976             :                         __LINE__,
     977             :                         src_dfs_name,
     978             :                         "renamed_file",
     979             :                         nt_errstr(status));
     980           0 :                 return false;
     981             :         }
     982             : 
     983           0 :         status = smb1_ntrename_rename(cli,
     984             :                                       src_dfs_name,
     985             :                                       "BAD\\BAD\\renamed_file");
     986           0 :         if (!NT_STATUS_IS_OK(status)) {
     987           0 :                 printf("%s:%d SMB1 ntrename rename of %s -> %s should "
     988             :                         "succeed got %s\n",
     989             :                         __FILE__,
     990             :                         __LINE__,
     991             :                         src_dfs_name,
     992             :                         "BAD\\BAD\\renamed_file",
     993             :                         nt_errstr(status));
     994           0 :                 return false;
     995             :         }
     996             : 
     997             :         /* Ensure we did rename. */
     998           0 :         status = get_smb1_crtime(cli,
     999             :                                 "BAD\\BAD\\renamed_file",
    1000             :                                 &test_crtime);
    1001           0 :         if (!NT_STATUS_IS_OK(status)) {
    1002           0 :                 printf("%s:%d Failed to get crtime "
    1003             :                         "for %s, (%s)\n",
    1004             :                         __FILE__,
    1005             :                         __LINE__,
    1006             :                         "BAD\\BAD\\renamed_file",
    1007             :                         nt_errstr(status));
    1008           0 :                 return false;
    1009             :         }
    1010             : 
    1011             :         /* Put it back. */
    1012           0 :         status = smb1_ntrename_rename(cli,
    1013             :                                       "BAD\\BAD\\renamed_file",
    1014             :                                        src_dfs_name);
    1015           0 :         if (!NT_STATUS_IS_OK(status)) {
    1016           0 :                 printf("%s:%d SMB1 ntrename rename of %s -> %s "
    1017             :                         "should succeed got %s\n",
    1018             :                         __FILE__,
    1019             :                         __LINE__,
    1020             :                         "BAD\\BAD\\renamed_file",
    1021             :                         src_dfs_name,
    1022             :                         nt_errstr(status));
    1023           0 :                 return false;
    1024             :         }
    1025             : 
    1026             :         /* Ensure we did rename. */
    1027           0 :         status = get_smb1_crtime(cli,
    1028             :                                 src_dfs_name,
    1029             :                                 &test_crtime);
    1030           0 :         if (!NT_STATUS_IS_OK(status)) {
    1031           0 :                 printf("%s:%d Failed to get crtime "
    1032             :                         "for %s, (%s)\n",
    1033             :                         __FILE__,
    1034             :                         __LINE__,
    1035             :                         src_dfs_name,
    1036             :                         nt_errstr(status));
    1037           0 :                 return false;
    1038             :         }
    1039             : 
    1040           0 :         return true;
    1041             : }
    1042             : 
    1043             : /*
    1044             :  * Hard link an SMB1 file on a DFS share. SMB1 ntrename version.
    1045             :  */
    1046           0 : static NTSTATUS smb1_ntrename_hardlink(struct cli_state *cli,
    1047             :                                        const char *src_dfs_name,
    1048             :                                        const char *target_name)
    1049             : {
    1050           0 :         return smb1_ntrename(cli,
    1051             :                              src_dfs_name,
    1052             :                              target_name,
    1053             :                              RENAME_FLAG_HARD_LINK);
    1054             : }
    1055             : 
    1056           0 : static bool test_smb1_ntrename_hardlink(struct cli_state *cli,
    1057             :                                         const char *src_dfs_name)
    1058             : {
    1059           0 :         struct timespec test_crtime = { 0 };
    1060           0 :         NTSTATUS status;
    1061           0 :         bool retval = false;
    1062             : 
    1063             :         /* Try with a non-DFS name. */
    1064           0 :         status = smb1_ntrename_hardlink(cli,
    1065             :                                         src_dfs_name,
    1066             :                                         "hlink");
    1067           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
    1068             :                 /* Fails I think as target becomes "" on server. */
    1069           0 :                 printf("%s:%d SMB1 ntrename of %s -> %s should get "
    1070             :                         "NT_STATUS_OBJECT_PATH_SYNTAX_BAD got %s\n",
    1071             :                         __FILE__,
    1072             :                         __LINE__,
    1073             :                         src_dfs_name,
    1074             :                         "hlink",
    1075             :                         nt_errstr(status));
    1076           0 :                 return false;
    1077             :         }
    1078             : 
    1079           0 :         status = smb1_ntrename_hardlink(cli,
    1080             :                                         src_dfs_name,
    1081             :                                         "BAD\\BAD\\hlink");
    1082           0 :         if (!NT_STATUS_IS_OK(status)) {
    1083           0 :                 printf("%s:%d SMB1 ntrename hardlink of %s -> %s "
    1084             :                         "should succeed got %s\n",
    1085             :                         __FILE__,
    1086             :                         __LINE__,
    1087             :                         src_dfs_name,
    1088             :                         "BAD\\BAD\\hlink",
    1089             :                         nt_errstr(status));
    1090           0 :                 goto out;
    1091             :         }
    1092             : 
    1093             :         /* Ensure we did hardlink. */
    1094           0 :         status = get_smb1_crtime(cli,
    1095             :                                 "BAD\\BAD\\hlink",
    1096             :                                 &test_crtime);
    1097           0 :         if (!NT_STATUS_IS_OK(status)) {
    1098           0 :                 printf("%s:%d Failed to get crtime "
    1099             :                         "for %s, (%s)\n",
    1100             :                         __FILE__,
    1101             :                         __LINE__,
    1102             :                         "BAD\\BAD\\hlink",
    1103             :                         nt_errstr(status));
    1104           0 :                 goto out;
    1105             :         }
    1106             : 
    1107           0 :         retval = smb1_crtime_matches(cli,
    1108             :                                     "BAD\\BAD\\hlink",
    1109             :                                     test_crtime,
    1110             :                                     src_dfs_name);
    1111           0 :         if (!retval) {
    1112           0 :                 printf("%s:%d smb1_crtime_matches failed for "
    1113             :                         "%s %s\n",
    1114             :                         __FILE__,
    1115             :                         __LINE__,
    1116             :                         src_dfs_name,
    1117             :                         "BAD\\BAD\\hlink");
    1118           0 :                 goto out;
    1119             :         }
    1120             : 
    1121           0 :   out:
    1122             : 
    1123             :         /* Remove the hardlink to clean up. */
    1124           0 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\hlink");
    1125           0 :         return retval;
    1126             : }
    1127             : 
    1128             : static void smb1_setfileinfo_done(struct tevent_req *subreq);
    1129             : 
    1130             : struct smb1_setfileinfo_state {
    1131             :         uint16_t setup;
    1132             :         uint8_t param[6];
    1133             :         uint8_t *data;
    1134             : };
    1135             : 
    1136           0 : static struct tevent_req *smb1_setfileinfo_send(TALLOC_CTX *mem_ctx,
    1137             :                                                 struct tevent_context *ev,
    1138             :                                                 struct cli_state *cli,
    1139             :                                                 uint16_t fnum,
    1140             :                                                 const char *target_name,
    1141             :                                                 uint16_t info_level)
    1142             : {
    1143           0 :         struct tevent_req *req = NULL;
    1144           0 :         struct tevent_req *subreq = NULL;
    1145           0 :         struct smb1_setfileinfo_state *state = NULL;
    1146           0 :         smb_ucs2_t *converted_str = NULL;
    1147           0 :         size_t converted_size_bytes = 0;
    1148           0 :         bool ok = false;
    1149             : 
    1150           0 :         req = tevent_req_create(mem_ctx,
    1151             :                                 &state,
    1152             :                                 struct smb1_setfileinfo_state);
    1153           0 :         if (req == NULL) {
    1154           0 :                 return NULL;
    1155             :         }
    1156             : 
    1157           0 :         PUSH_LE_U16(&state->setup, 0, TRANSACT2_SETPATHINFO);
    1158             : 
    1159           0 :         PUSH_LE_U16(state->param, 0, fnum);
    1160           0 :         PUSH_LE_U16(state->param, 2, info_level);
    1161             : 
    1162           0 :         ok = push_ucs2_talloc(state,
    1163             :                               &converted_str,
    1164             :                               target_name,
    1165             :                               &converted_size_bytes);
    1166           0 :         if (!ok) {
    1167           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1168           0 :                 return tevent_req_post(req, ev);
    1169             :         }
    1170             : 
    1171             :         /*
    1172             :          * W2K8 insists the dest name is not null
    1173             :          * terminated. Remove the last 2 zero bytes
    1174             :          * and reduce the name length.
    1175             :          */
    1176             : 
    1177           0 :         if (converted_size_bytes < 2) {
    1178           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1179           0 :                 return tevent_req_post(req, ev);
    1180             :         }
    1181           0 :         converted_size_bytes -= 2;
    1182             : 
    1183           0 :         state->data = talloc_zero_array(state,
    1184             :                                         uint8_t,
    1185             :                                         12 + converted_size_bytes);
    1186           0 :         if (tevent_req_nomem(state->data, req)) {
    1187           0 :                 return tevent_req_post(req, ev);
    1188             :         }
    1189             : 
    1190           0 :         SIVAL(state->data, 8, converted_size_bytes);
    1191           0 :         memcpy(state->data + 12, converted_str, converted_size_bytes);
    1192             : 
    1193           0 :         subreq = cli_trans_send(state, /* mem ctx. */
    1194             :                                 ev,/* event ctx. */
    1195             :                                 cli,/* cli_state. */
    1196             :                                 0,/* additional_flags2 */
    1197             :                                 SMBtrans2,              /* cmd. */
    1198             :                                 NULL,/* pipe name. */
    1199             :                                 -1,/* fid. */
    1200             :                                 0,/* function. */
    1201             :                                 0,/* flags. */
    1202           0 :                                 &state->setup,/* setup. */
    1203             :                                 1,/* num setup uint16_t words. */
    1204             :                                 0,/* max returned setup. */
    1205           0 :                                 state->param,/* param. */
    1206             :                                 6,/* num param. */
    1207             :                                 2,/* max returned param. */
    1208           0 :                                 state->data,/* data. */
    1209           0 :                                 talloc_get_size(state->data),/* num data. */
    1210             :                                 0);/* max returned data. */
    1211             : 
    1212           0 :         if (tevent_req_nomem(subreq, req)) {
    1213           0 :                 return tevent_req_post(req, ev);
    1214             :         }
    1215           0 :         tevent_req_set_callback(subreq, smb1_setfileinfo_done, req);
    1216           0 :         return req;
    1217             : }
    1218             : 
    1219           0 : static void smb1_setfileinfo_done(struct tevent_req *subreq)
    1220             : {
    1221           0 :         NTSTATUS status = cli_trans_recv(subreq,
    1222             :                                          NULL,
    1223             :                                          NULL,
    1224             :                                          NULL,
    1225             :                                          0,
    1226             :                                          NULL,
    1227             :                                          NULL,
    1228             :                                          0,
    1229             :                                          NULL,
    1230             :                                          NULL,
    1231             :                                          0,
    1232             :                                          NULL);
    1233           0 :         tevent_req_simple_finish_ntstatus(subreq,
    1234             :                                           status);
    1235           0 : }
    1236             : 
    1237           0 : static NTSTATUS smb1_setfileinfo_recv(struct tevent_req *req)
    1238             : {
    1239           0 :         return tevent_req_simple_recv_ntstatus(req);
    1240             : }
    1241             : 
    1242             : /*
    1243             :  * Rename or hardlink an SMB1 file on a DFS share.
    1244             :  * setfileinfo (file handle + target pathname) version.
    1245             :  */
    1246           0 : static NTSTATUS smb1_setfileinfo(struct cli_state *cli,
    1247             :                                  uint16_t fnum,
    1248             :                                  const char *target_name,
    1249             :                                  uint16_t info_level)
    1250             : {
    1251           0 :         TALLOC_CTX *frame = NULL;
    1252           0 :         struct tevent_context *ev;
    1253           0 :         struct tevent_req *req;
    1254           0 :         NTSTATUS status;
    1255             : 
    1256           0 :         frame = talloc_stackframe();
    1257             : 
    1258           0 :         ev = samba_tevent_context_init(frame);
    1259           0 :         if (ev == NULL) {
    1260           0 :                 status = NT_STATUS_NO_MEMORY;
    1261           0 :                 goto fail;
    1262             :         }
    1263             : 
    1264           0 :         req = smb1_setfileinfo_send(frame,
    1265             :                                     ev,
    1266             :                                     cli,
    1267             :                                     fnum,
    1268             :                                     target_name,
    1269             :                                     info_level);
    1270           0 :         if (req == NULL) {
    1271           0 :                 status = NT_STATUS_NO_MEMORY;
    1272           0 :                 goto fail;
    1273             :         }
    1274             : 
    1275           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    1276           0 :                 goto fail;
    1277             :         }
    1278             : 
    1279           0 :         status = smb1_setfileinfo_recv(req);
    1280             : 
    1281           0 :   fail:
    1282             : 
    1283           0 :         TALLOC_FREE(frame);
    1284           0 :         return status;
    1285             : }
    1286             : 
    1287           0 : static NTSTATUS smb1_setfileinfo_rename(struct cli_state *cli,
    1288             :                                         uint16_t fnum,
    1289             :                                         const char *target_name)
    1290             : {
    1291           0 :         return smb1_setfileinfo(cli,
    1292             :                                 fnum,
    1293             :                                 target_name,
    1294             :                                 SMB_FILE_RENAME_INFORMATION);
    1295             : }
    1296             : 
    1297             : /*
    1298             :  * On Windows, rename using a file handle as source
    1299             :  * is not supported.
    1300             :  */
    1301             : 
    1302           0 : static bool test_smb1_setfileinfo_rename(struct cli_state *cli,
    1303             :                                          const char *src_dfs_name)
    1304             : {
    1305           0 :         uint16_t fnum = (uint16_t)-1;
    1306           0 :         NTSTATUS status;
    1307           0 :         bool retval = false;
    1308             : 
    1309             :         /* First open the source file. */
    1310           0 :         status = smb1cli_ntcreatex(cli->conn,
    1311           0 :                                    cli->timeout,
    1312             :                                    cli->smb1.pid,
    1313             :                                    cli->smb1.tcon,
    1314             :                                    cli->smb1.session,
    1315             :                                    src_dfs_name,
    1316             :                                    OPLOCK_NONE, /* CreatFlags */
    1317             :                                    0, /* RootDirectoryFid */
    1318             :                                    SEC_STD_SYNCHRONIZE|
    1319             :                                         SEC_STD_DELETE, /* DesiredAccess */
    1320             :                                    0, /* AllocationSize */
    1321             :                                    FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
    1322             :                                    FILE_SHARE_READ|
    1323             :                                         FILE_SHARE_WRITE|
    1324             :                                         FILE_SHARE_DELETE, /* ShareAccess */
    1325             :                                    FILE_OPEN, /* CreateDisposition */
    1326             :                                    0, /* CreateOptions */
    1327             :                                    2, /* ImpersonationLevel */
    1328             :                                    0, /* SecurityFlags */
    1329             :                                    &fnum);
    1330           0 :         if (!NT_STATUS_IS_OK(status)) {
    1331           0 :                 printf("%s:%d failed to open %s, %s\n",
    1332             :                         __FILE__,
    1333             :                         __LINE__,
    1334             :                         src_dfs_name,
    1335             :                         nt_errstr(status));
    1336           0 :                 goto out;
    1337             :         }
    1338             : 
    1339             :         /*
    1340             :          * On Windows rename given a file handle returns
    1341             :          * NT_STATUS_UNSUCCESSFUL (not documented in MS-SMB).
    1342             :          */
    1343             : 
    1344           0 :         status = smb1_setfileinfo_rename(cli,
    1345             :                                          fnum,
    1346             :                                          "BAD\\BAD\\renamed_file");
    1347           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL)) {
    1348           0 :                 printf("%s:%d SMB1 setfileinfo rename of %s -> %s should get "
    1349             :                         "NT_STATUS_UNSUCCESSFUL got %s\n",
    1350             :                         __FILE__,
    1351             :                         __LINE__,
    1352             :                         src_dfs_name,
    1353             :                         "BAD\\BAD\\hlink",
    1354             :                         nt_errstr(status));
    1355           0 :                 goto out;
    1356             :         }
    1357             : 
    1358             :         /* Try with a non-DFS name - still gets NT_STATUS_UNSUCCESSFUL. */
    1359           0 :         status = smb1_setfileinfo_rename(cli,
    1360             :                                          fnum,
    1361             :                                          "renamed_file");
    1362           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL)) {
    1363           0 :                 printf("%s:%d SMB1 setfileinfo rename of %s -> %s should get "
    1364             :                         "NT_STATUS_UNSUCCESSFUL got %s\n",
    1365             :                         __FILE__,
    1366             :                         __LINE__,
    1367             :                         src_dfs_name,
    1368             :                         "hlink",
    1369             :                         nt_errstr(status));
    1370           0 :                 goto out;
    1371             :         }
    1372             : 
    1373           0 :         retval = true;
    1374             : 
    1375           0 :   out:
    1376             : 
    1377           0 :         if (fnum != (uint16_t)-1) {
    1378           0 :                 (void)smb1cli_close(cli->conn,
    1379           0 :                                     cli->timeout,
    1380             :                                     cli->smb1.pid,
    1381             :                                     cli->smb1.tcon,
    1382             :                                     cli->smb1.session,
    1383             :                                     fnum,
    1384             :                                     0); /* last_modified */
    1385             :         }
    1386             : 
    1387           0 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\renamed_file");
    1388           0 :         return retval;
    1389             : }
    1390             : 
    1391             : 
    1392           0 : static NTSTATUS smb1_setfileinfo_hardlink(struct cli_state *cli,
    1393             :                                           uint16_t fnum,
    1394             :                                           const char *target_name)
    1395             : {
    1396           0 :         return smb1_setfileinfo(cli,
    1397             :                                 fnum,
    1398             :                                 target_name,
    1399             :                                 SMB_FILE_LINK_INFORMATION);
    1400             : }
    1401             : 
    1402             : /*
    1403             :  * On Windows, hardlink using a file handle as source
    1404             :  * is not supported.
    1405             :  */
    1406             : 
    1407           0 : static bool test_smb1_setfileinfo_hardlink(struct cli_state *cli,
    1408             :                                            const char *src_dfs_name)
    1409             : {
    1410           0 :         uint16_t fnum = (uint16_t)-1;
    1411           0 :         NTSTATUS status;
    1412           0 :         bool retval = false;
    1413             : 
    1414             :         /* First open the source file. */
    1415           0 :         status = smb1cli_ntcreatex(cli->conn,
    1416           0 :                                    cli->timeout,
    1417             :                                    cli->smb1.pid,
    1418             :                                    cli->smb1.tcon,
    1419             :                                    cli->smb1.session,
    1420             :                                    src_dfs_name,
    1421             :                                    OPLOCK_NONE, /* CreatFlags */
    1422             :                                    0, /* RootDirectoryFid */
    1423             :                                    SEC_STD_SYNCHRONIZE|
    1424             :                                         SEC_RIGHTS_FILE_READ, /* DesiredAccess */
    1425             :                                    0, /* AllocationSize */
    1426             :                                    FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
    1427             :                                    FILE_SHARE_READ|
    1428             :                                         FILE_SHARE_WRITE|
    1429             :                                         FILE_SHARE_DELETE, /* ShareAccess */
    1430             :                                    FILE_OPEN, /* CreateDisposition */
    1431             :                                    0, /* CreateOptions */
    1432             :                                    2, /* ImpersonationLevel */
    1433             :                                    0, /* SecurityFlags */
    1434             :                                    &fnum);
    1435           0 :         if (!NT_STATUS_IS_OK(status)) {
    1436           0 :                 printf("%s:%d failed to open %s, %s\n",
    1437             :                         __FILE__,
    1438             :                         __LINE__,
    1439             :                         src_dfs_name,
    1440             :                         nt_errstr(status));
    1441           0 :                 goto out;
    1442             :         }
    1443             : 
    1444             :         /*
    1445             :          * On Windows hardlink given a file handle returns
    1446             :          * NT_STATUS_UNSUCCESSFUL (not documented in MS-SMB).
    1447             :          */
    1448             : 
    1449           0 :         status = smb1_setfileinfo_hardlink(cli,
    1450             :                                            fnum,
    1451             :                                            "BAD\\BAD\\hlink");
    1452           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL)) {
    1453           0 :                 printf("%s:%d SMB1 setfileinfo hardlink of %s -> %s should get "
    1454             :                         "NT_STATUS_UNSUCCESSFUL got %s\n",
    1455             :                         __FILE__,
    1456             :                         __LINE__,
    1457             :                         src_dfs_name,
    1458             :                         "BAD\\BAD\\hlink",
    1459             :                         nt_errstr(status));
    1460           0 :                 goto out;
    1461             :         }
    1462             : 
    1463             :         /* Try with a non-DFS name - still gets NT_STATUS_UNSUCCESSFUL. */
    1464           0 :         status = smb1_setfileinfo_hardlink(cli,
    1465             :                                          fnum,
    1466             :                                          "hlink");
    1467           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL)) {
    1468           0 :                 printf("%s:%d SMB1 setfileinfo hardlink of %s -> %s should get "
    1469             :                         "NT_STATUS_UNSUCCESSFUL got %s\n",
    1470             :                         __FILE__,
    1471             :                         __LINE__,
    1472             :                         src_dfs_name,
    1473             :                         "hlink",
    1474             :                         nt_errstr(status));
    1475           0 :                 goto out;
    1476             :         }
    1477             : 
    1478           0 :         retval = true;
    1479             : 
    1480           0 :   out:
    1481             : 
    1482           0 :         if (fnum != (uint16_t)-1) {
    1483           0 :                 (void)smb1cli_close(cli->conn,
    1484           0 :                                     cli->timeout,
    1485             :                                     cli->smb1.pid,
    1486             :                                     cli->smb1.tcon,
    1487             :                                     cli->smb1.session,
    1488             :                                     fnum,
    1489             :                                     0); /* last_modified */
    1490             :         }
    1491             : 
    1492           0 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\hlink");
    1493           0 :         return retval;
    1494             : }
    1495             : 
    1496             : /*
    1497             :  * According to:
    1498             : 
    1499             :  * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/dc9978d7-6299-4c5a-a22d-a039cdc716ea
    1500             :  *
    1501             :  *  (Characters " \ / [ ] : | < > + = ; , * ?,
    1502             :  *  and control characters in range 0x00 through
    1503             :  *  0x1F, inclusive, are illegal in a share name)
    1504             :  *
    1505             :  * But Windows server only checks in DFS sharenames ':'. All other
    1506             :  * share names are allowed.
    1507             :  */
    1508             : 
    1509           0 : static bool test_smb1_dfs_sharenames(struct cli_state *cli,
    1510             :                                      const char *dfs_root_share_name,
    1511             :                                      struct timespec root_crtime)
    1512             : {
    1513           0 :         char test_path[20];
    1514           0 :         const char *test_str = "/[]:|<>+=;,*?";
    1515           0 :         const char *p;
    1516           0 :         unsigned int i;
    1517           0 :         bool crtime_matched = false;
    1518             : 
    1519             :         /* Setup template pathname. */
    1520           0 :         memcpy(test_path, "\\SERVER\\X", 10);
    1521             : 
    1522             :         /* Test invalid control characters. */
    1523           0 :         for (i = 1; i < 0x20; i++) {
    1524           0 :                 test_path[8] = i;
    1525           0 :                 crtime_matched = smb1_crtime_matches(cli,
    1526             :                                          dfs_root_share_name,
    1527             :                                          root_crtime,
    1528             :                                          test_path);
    1529           0 :                 if (!crtime_matched) {
    1530           0 :                         return false;
    1531             :                 }
    1532             :         }
    1533             : 
    1534             :         /* Test explicit invalid characters. */
    1535           0 :         for (p = test_str; *p != '\0'; p++) {
    1536           0 :                 test_path[8] = *p;
    1537           0 :                 if (*p == ':') {
    1538             :                         /*
    1539             :                          * Only ':' is treated as an INVALID sharename
    1540             :                          * for a DFS SERVER\\SHARE path.
    1541             :                          */
    1542           0 :                         struct timespec test_crtime = { 0 };
    1543           0 :                         NTSTATUS status = get_smb1_crtime(cli,
    1544             :                                                          test_path,
    1545             :                                                          &test_crtime);
    1546           0 :                         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
    1547           0 :                                 printf("%s:%d Open of %s should get "
    1548             :                                         "NT_STATUS_OBJECT_NAME_INVALID, got %s\n",
    1549             :                                         __FILE__,
    1550             :                                         __LINE__,
    1551             :                                         test_path,
    1552             :                                         nt_errstr(status));
    1553           0 :                                 return false;
    1554             :                         }
    1555             :                 } else {
    1556           0 :                         crtime_matched = smb1_crtime_matches(cli,
    1557             :                                                  dfs_root_share_name,
    1558             :                                                  root_crtime,
    1559             :                                                  test_path);
    1560           0 :                         if (!crtime_matched) {
    1561           0 :                                 return false;
    1562             :                         }
    1563             :                 }
    1564             :         }
    1565           0 :         return true;
    1566             : }
    1567             : 
    1568             : /*
    1569             :  * "Raw" test of SMB1 paths to a DFS share.
    1570             :  * We must (mostly) use the lower level smb1cli_XXXX() interfaces,
    1571             :  * not the cli_XXX() ones here as the ultimate goal is to fix our
    1572             :  * cli_XXX() interfaces to work transparently over DFS.
    1573             :  *
    1574             :  * So here, we're testing the server code, not the client code.
    1575             :  *
    1576             :  * Passes cleanly against Windows.
    1577             :  */
    1578             : 
    1579           2 : bool run_smb1_dfs_paths(int dummy)
    1580             : {
    1581           2 :         struct cli_state *cli = NULL;
    1582           0 :         NTSTATUS status;
    1583           2 :         bool dfs_supported = false;
    1584           2 :         char *dfs_root_share_name = NULL;
    1585           2 :         struct timespec root_crtime = { 0 };
    1586           2 :         struct timespec test_crtime = { 0 };
    1587           2 :         bool crtime_matched = false;
    1588           2 :         bool retval = false;
    1589           2 :         bool ok = false;
    1590           2 :         bool equal = false;
    1591           0 :         unsigned int i;
    1592           2 :         uint16_t fnum = (uint16_t)-1;
    1593             : 
    1594           2 :         printf("Starting SMB1-DFS-PATHS\n");
    1595             : 
    1596           2 :         if (!torture_init_connection(&cli)) {
    1597           0 :                 return false;
    1598             :         }
    1599             : 
    1600           2 :         if (!torture_open_connection(&cli, 0)) {
    1601           0 :                 return false;
    1602             :         }
    1603             : 
    1604             :         /* Ensure this is a DFS share. */
    1605           2 :         dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
    1606           2 :         if (!dfs_supported) {
    1607           0 :                 printf("Server %s does not support DFS\n",
    1608           0 :                         smbXcli_conn_remote_name(cli->conn));
    1609           0 :                 return false;
    1610             :         }
    1611           2 :         dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb1.tcon);
    1612           2 :         if (!dfs_supported) {
    1613           0 :                 printf("Share %s does not support DFS\n",
    1614           0 :                         cli->share);
    1615           0 :                 return false;
    1616             :         }
    1617             : 
    1618             :         /* Start with an empty share. */
    1619           2 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\BAD");
    1620           2 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\file");
    1621           2 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\renamed_file");
    1622           2 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\hlink");
    1623             : 
    1624             :         /*
    1625             :          * Create the "official" DFS share root name.
    1626             :          */
    1627           2 :         dfs_root_share_name = talloc_asprintf(talloc_tos(),
    1628             :                                         "\\%s\\%s",
    1629           2 :                                         smbXcli_conn_remote_name(cli->conn),
    1630           2 :                                         cli->share);
    1631           2 :         if (dfs_root_share_name == NULL) {
    1632           0 :                 printf("Out of memory\n");
    1633           0 :                 return false;
    1634             :         }
    1635             : 
    1636             :         /* Get the share root crtime. */
    1637           2 :         status = get_smb1_crtime(cli,
    1638             :                                 dfs_root_share_name,
    1639             :                                 &root_crtime);
    1640           2 :         if (!NT_STATUS_IS_OK(status)) {
    1641           0 :                 printf("%s:%d Failed to get crtime for share root %s, (%s)\n",
    1642             :                         __FILE__,
    1643             :                         __LINE__,
    1644             :                         dfs_root_share_name,
    1645             :                         nt_errstr(status));
    1646           0 :                 return false;
    1647             :         }
    1648             : 
    1649             :         /*
    1650             :          * Test the Windows algorithm for parsing DFS names.
    1651             :          */
    1652             :         /*
    1653             :          * A single "SERVER" element should open and match the share root.
    1654             :          */
    1655           2 :         crtime_matched = smb1_crtime_matches(cli,
    1656             :                                          dfs_root_share_name,
    1657             :                                          root_crtime,
    1658           2 :                                          smbXcli_conn_remote_name(cli->conn));
    1659           2 :         if (!crtime_matched) {
    1660           0 :                 printf("%s:%d Failed to match crtime for %s\n",
    1661             :                         __FILE__,
    1662             :                         __LINE__,
    1663           0 :                         smbXcli_conn_remote_name(cli->conn));
    1664           0 :                 return false;
    1665             :         }
    1666             : 
    1667             :         /* An "" (empty) server name should open and match the share root. */
    1668           2 :         crtime_matched = smb1_crtime_matches(cli,
    1669             :                                          dfs_root_share_name,
    1670             :                                          root_crtime,
    1671             :                                          "");
    1672           2 :         if (!crtime_matched) {
    1673           0 :                 printf("%s:%d Failed to match crtime for %s\n",
    1674             :                         __FILE__,
    1675             :                         __LINE__,
    1676             :                         "");
    1677           0 :                 return false;
    1678             :         }
    1679             : 
    1680             :         /*
    1681             :          * For SMB1 the server just strips off any number of leading '\\'
    1682             :          * characters. Show this is the case.
    1683             :          */
    1684          22 :         for (i = 0; i < 10; i++) {
    1685           0 :                 char leading_backslash_name[20];
    1686          20 :                 leading_backslash_name[i] = '\\';
    1687          20 :                 memcpy(&leading_backslash_name[i+1],
    1688             :                         "SERVER",
    1689             :                         strlen("SERVER")+1);
    1690             : 
    1691          20 :                 crtime_matched = smb1_crtime_matches(cli,
    1692             :                                          dfs_root_share_name,
    1693             :                                          root_crtime,
    1694             :                                          leading_backslash_name);
    1695          20 :                 if (!crtime_matched) {
    1696           0 :                         printf("%s:%d Failed to match crtime for %s\n",
    1697             :                                 __FILE__,
    1698             :                                 __LINE__,
    1699             :                                 leading_backslash_name);
    1700           0 :                         return false;
    1701             :                 }
    1702             :         }
    1703             : 
    1704             :         /* A "BAD" server name should open and match the share root. */
    1705           2 :         crtime_matched = smb1_crtime_matches(cli,
    1706             :                                          dfs_root_share_name,
    1707             :                                          root_crtime,
    1708             :                                          "BAD");
    1709           2 :         if (!crtime_matched) {
    1710           0 :                 printf("%s:%d Failed to match crtime for %s\n",
    1711             :                         __FILE__,
    1712             :                         __LINE__,
    1713             :                         "BAD");
    1714           0 :                 return false;
    1715             :         }
    1716             :         /*
    1717             :          * A "BAD\\BAD" server and share name should open
    1718             :          * and match the share root.
    1719             :          */
    1720           2 :         crtime_matched = smb1_crtime_matches(cli,
    1721             :                                          dfs_root_share_name,
    1722             :                                          root_crtime,
    1723             :                                          "BAD\\BAD");
    1724           2 :         if (!crtime_matched) {
    1725           0 :                 printf("%s:%d Failed to match crtime for %s\n",
    1726             :                         __FILE__,
    1727             :                         __LINE__,
    1728             :                         "BAD\\BAD");
    1729           0 :                 return false;
    1730             :         }
    1731             :         /*
    1732             :          * Trying to open "BAD\\BAD\\BAD" should get
    1733             :          * NT_STATUS_OBJECT_NAME_NOT_FOUND.
    1734             :          */
    1735           2 :         status = get_smb1_crtime(cli,
    1736             :                                 "BAD\\BAD\\BAD",
    1737             :                                 &test_crtime);
    1738           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    1739           0 :                 printf("%s:%d Open of %s should get "
    1740             :                         "STATUS_OBJECT_NAME_NOT_FOUND, got %s\n",
    1741             :                         __FILE__,
    1742             :                         __LINE__,
    1743             :                         "BAD\\BAD\\BAD",
    1744             :                         nt_errstr(status));
    1745           0 :                 return false;
    1746             :         }
    1747             :         /*
    1748             :          * Trying to open "BAD\\BAD\\BAD\\BAD" should get
    1749             :          * NT_STATUS_OBJECT_PATH_NOT_FOUND.
    1750             :          */
    1751           2 :         status = get_smb1_crtime(cli,
    1752             :                                 "BAD\\BAD\\BAD\\BAD",
    1753             :                                 &test_crtime);
    1754           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
    1755           0 :                 printf("%s:%d Open of %s should get "
    1756             :                         "STATUS_OBJECT_NAME_NOT_FOUND, got %s\n",
    1757             :                         __FILE__,
    1758             :                         __LINE__,
    1759             :                         "BAD\\BAD\\BAD\\BAD",
    1760             :                         nt_errstr(status));
    1761           0 :                 return false;
    1762             :         }
    1763             :         /*
    1764             :          * Test for invalid pathname characters in the servername.
    1765             :          * They are ignored, and it still opens the share root.
    1766             :          */
    1767           2 :         crtime_matched = smb1_crtime_matches(cli,
    1768             :                                          dfs_root_share_name,
    1769             :                                          root_crtime,
    1770             :                                          "::::");
    1771           2 :         if (!crtime_matched) {
    1772           2 :                 printf("%s:%d Failed to match crtime for %s\n",
    1773             :                         __FILE__,
    1774             :                         __LINE__,
    1775             :                         "::::");
    1776           2 :                 return false;
    1777             :         }
    1778             : 
    1779             :         /*
    1780             :          * Test for invalid pathname characters in the sharename.
    1781             :          * Invalid sharename characters should still be flagged as
    1782             :          * NT_STATUS_OBJECT_NAME_INVALID. It turns out only ':'
    1783             :          * is considered an invalid sharename character.
    1784             :          */
    1785           0 :         ok = test_smb1_dfs_sharenames(cli,
    1786             :                                       dfs_root_share_name,
    1787             :                                       root_crtime);
    1788           0 :         if (!ok) {
    1789           0 :                 return false;
    1790             :         }
    1791             : 
    1792           0 :         status = smb1cli_ntcreatex(cli->conn,
    1793           0 :                                    cli->timeout,
    1794           0 :                                    cli->smb1.pid,
    1795           0 :                                    cli->smb1.tcon,
    1796           0 :                                    cli->smb1.session,
    1797             :                                    "BAD\\BAD\\file",
    1798             :                                    OPLOCK_NONE, /* CreatFlags */
    1799             :                                    0, /* RootDirectoryFid */
    1800             :                                    SEC_STD_SYNCHRONIZE|
    1801             :                                         SEC_STD_DELETE |
    1802             :                                         SEC_FILE_READ_DATA|
    1803             :                                         SEC_FILE_READ_ATTRIBUTE, /* DesiredAccess */
    1804             :                                    0, /* AllocationSize */
    1805             :                                    FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
    1806             :                                    FILE_SHARE_READ|
    1807             :                                         FILE_SHARE_WRITE|
    1808             :                                         FILE_SHARE_DELETE, /* ShareAccess */
    1809             :                                    FILE_CREATE, /* CreateDisposition */
    1810             :                                    0, /* CreateOptions */
    1811             :                                    2, /* ImpersonationLevel */
    1812             :                                    0, /* SecurityFlags */
    1813             :                                    &fnum);
    1814           0 :         if (!NT_STATUS_IS_OK(status)) {
    1815           0 :                 printf("%s:%d smb1cli_ntcreatex on %s returned %s\n",
    1816             :                         __FILE__,
    1817             :                         __LINE__,
    1818             :                         "BAD\\BAD\\file",
    1819             :                         nt_errstr(status));
    1820           0 :                 return false;
    1821             :         }
    1822             : 
    1823             :         /* Close "file" handle. */
    1824           0 :         (void)smb1cli_close(cli->conn,
    1825           0 :                             cli->timeout,
    1826           0 :                             cli->smb1.pid,
    1827           0 :                             cli->smb1.tcon,
    1828           0 :                             cli->smb1.session,
    1829             :                             fnum,
    1830             :                             0); /* last_modified */
    1831           0 :         fnum = (uint16_t)-1;
    1832             : 
    1833             :         /*
    1834             :          * Trying to open "BAD\\BAD\\file" should now get
    1835             :          * a valid crtime.
    1836             :          */
    1837           0 :         status = get_smb1_crtime(cli,
    1838             :                                 "BAD\\BAD\\file",
    1839             :                                 &test_crtime);
    1840           0 :         if (!NT_STATUS_IS_OK(status)) {
    1841           0 :                 printf("%s:%d Open of %s should succeed "
    1842             :                         "got %s\n",
    1843             :                         __FILE__,
    1844             :                         __LINE__,
    1845             :                         "BAD\\BAD\\file",
    1846             :                         nt_errstr(status));
    1847           0 :                 goto err;
    1848             :         }
    1849             : 
    1850             :         /*
    1851             :          * This crtime must be different from the root_crtime.
    1852             :          * This checks we're actually correctly reading crtimes
    1853             :          * from the filesystem.
    1854             :          */
    1855           0 :         equal = (timespec_compare(&test_crtime, &root_crtime) == 0);
    1856           0 :         if (equal) {
    1857           0 :                 printf("%s:%d Error. crtime of %s must differ from "
    1858             :                         "root_crtime\n",
    1859             :                         __FILE__,
    1860             :                         __LINE__,
    1861             :                         "BAD\\BAD\\file");
    1862           0 :                 goto err;
    1863             :         }
    1864             : 
    1865             :         /*
    1866             :          * Test different SMB1 renames
    1867             :          * and hard links.
    1868             :          */
    1869             : 
    1870             :         /* SMBmv only does rename. */
    1871           0 :         ok = test_smb1_mv(cli,
    1872             :                           "BAD\\BAD\\file");
    1873           0 :         if (!ok) {
    1874           0 :                 goto err;
    1875             :         }
    1876             : 
    1877           0 :         ok = test_smb1_setpathinfo_rename(cli,
    1878             :                                           "BAD\\BAD\\file");
    1879           0 :         if (!ok) {
    1880           0 :                 goto err;
    1881             :         }
    1882             : 
    1883           0 :         ok = test_smb1_setpathinfo_hardlink(cli,
    1884             :                                             "BAD\\BAD\\file");
    1885           0 :         if (!ok) {
    1886           0 :                 goto err;
    1887             :         }
    1888             : 
    1889           0 :         ok = test_smb1_setfileinfo_rename(cli,
    1890             :                                           "BAD\\BAD\\file");
    1891           0 :         if (!ok) {
    1892           0 :                 goto err;
    1893             :         }
    1894             : 
    1895           0 :         ok = test_smb1_setfileinfo_hardlink(cli,
    1896             :                                             "BAD\\BAD\\file");
    1897           0 :         if (!ok) {
    1898           0 :                 goto err;
    1899             :         }
    1900             : 
    1901           0 :         ok = test_smb1_ntrename_rename(cli,
    1902             :                                        "BAD\\BAD\\file");
    1903           0 :         if (!ok) {
    1904           0 :                 goto err;
    1905             :         }
    1906             : 
    1907           0 :         ok = test_smb1_ntrename_hardlink(cli,
    1908             :                                           "BAD\\BAD\\file");
    1909           0 :         if (!ok) {
    1910           0 :                 goto err;
    1911             :         }
    1912             : 
    1913           0 :         retval = true;
    1914             : 
    1915           0 :   err:
    1916             : 
    1917           0 :         if (fnum != (uint16_t)-1) {
    1918           0 :                 (void)smb1cli_close(cli->conn,
    1919           0 :                                     cli->timeout,
    1920           0 :                                     cli->smb1.pid,
    1921           0 :                                     cli->smb1.tcon,
    1922           0 :                                     cli->smb1.session,
    1923             :                                     fnum,
    1924             :                                     0); /* last_modified */
    1925             :         }
    1926             : 
    1927             :         /* Delete anything we made. */
    1928           0 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\BAD");
    1929           0 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\file");
    1930           0 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\renamed_file");
    1931           0 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\hlink");
    1932           0 :         return retval;
    1933             : }
    1934             : 
    1935             : /*
    1936             :  * SMB1 Findfirst. This is a minimal implementation
    1937             :  * that expects all filename returns in one packet.
    1938             :  * We're only using this to test the search DFS pathname
    1939             :  * parsing.
    1940             :  */
    1941             : 
    1942             : /****************************************************************************
    1943             :  Calculate a safe next_entry_offset.
    1944             : ****************************************************************************/
    1945             : 
    1946          30 : static size_t calc_next_entry_offset(const uint8_t *base,
    1947             :                                      const uint8_t *pdata_end)
    1948             : {
    1949          30 :         size_t next_entry_offset = (size_t)PULL_LE_U32(base,0);
    1950             : 
    1951          30 :         if (next_entry_offset == 0 ||
    1952          30 :                         base + next_entry_offset < base ||
    1953          30 :                         base + next_entry_offset > pdata_end) {
    1954           0 :                 next_entry_offset = pdata_end - base;
    1955             :         }
    1956          30 :         return next_entry_offset;
    1957             : }
    1958             : 
    1959          30 : static size_t get_filename(TALLOC_CTX *ctx,
    1960             :                            struct cli_state *cli,
    1961             :                            const uint8_t *base_ptr,
    1962             :                            uint16_t recv_flags2,
    1963             :                            const uint8_t *p,
    1964             :                            const uint8_t *pdata_end,
    1965             :                            struct file_info *finfo)
    1966             : {
    1967          30 :         size_t ret = 0;
    1968          30 :         const uint8_t *base = p;
    1969          30 :         size_t namelen = 0;
    1970          30 :         size_t slen = 0;
    1971             : 
    1972          30 :         ZERO_STRUCTP(finfo);
    1973             : 
    1974          30 :         if (pdata_end - base < 94) {
    1975           0 :                 return pdata_end - base;
    1976             :         }
    1977          30 :         p += 4; /* next entry offset */
    1978          30 :         p += 4; /* fileindex */
    1979             :         /* Offset zero is "create time", not "change time". */
    1980          30 :         p += 8;
    1981          30 :         finfo->atime_ts = interpret_long_date(BVAL(p, 0));
    1982          30 :         p += 8;
    1983          30 :         finfo->mtime_ts = interpret_long_date(BVAL(p, 0));
    1984          30 :         p += 8;
    1985          30 :         finfo->ctime_ts = interpret_long_date(BVAL(p, 0));
    1986          30 :         p += 8;
    1987          30 :         finfo->size = PULL_LE_U64(p, 0);
    1988          30 :         p += 8;
    1989          30 :         p += 8; /* alloc size */
    1990          30 :         finfo->attr = PULL_LE_U32(p, 0);
    1991          30 :         p += 4;
    1992          30 :         namelen = PULL_LE_U32(p, 0);
    1993          30 :         p += 4;
    1994          30 :         p += 4; /* EA size */
    1995          30 :         slen = PULL_LE_U8(p, 0);
    1996          30 :         if (slen > 24) {
    1997             :                 /* Bad short name length. */
    1998           0 :                 return pdata_end - base;
    1999             :         }
    2000          30 :         p += 2;
    2001          30 :         ret = pull_string_talloc(ctx,
    2002             :                                  base_ptr,
    2003             :                                  recv_flags2,
    2004             :                                  &finfo->short_name,
    2005             :                                  p,
    2006             :                                  slen,
    2007             :                                  STR_UNICODE);
    2008          30 :         if (ret == (size_t)-1) {
    2009           0 :                 return pdata_end - base;
    2010             :         }
    2011          30 :         p += 24; /* short name */
    2012          30 :         if (p + namelen < p || p + namelen > pdata_end) {
    2013           0 :                 return pdata_end - base;
    2014             :         }
    2015          30 :         ret = pull_string_talloc(ctx,
    2016             :                                  base_ptr,
    2017             :                                  recv_flags2,
    2018             :                                  &finfo->name,
    2019             :                                  p,
    2020             :                                  namelen,
    2021             :                                  0);
    2022          30 :         if (ret == (size_t)-1) {
    2023           0 :                 return pdata_end - base;
    2024             :         }
    2025          30 :         return calc_next_entry_offset(base, pdata_end);
    2026             : }
    2027             : 
    2028             : /* Single shot SMB1 TRANS2 FindFirst. */
    2029             : 
    2030          10 : static NTSTATUS smb1_findfirst(TALLOC_CTX *mem_ctx,
    2031             :                                struct cli_state *cli,
    2032             :                                const char *search_name,
    2033             :                                struct file_info **names,
    2034             :                                size_t *num_names)
    2035             : {
    2036           0 :         NTSTATUS status;
    2037           0 :         uint16_t setup[1];
    2038          10 :         uint8_t *param = NULL;
    2039          10 :         uint16_t recv_flags2 = 0;
    2040          10 :         uint8_t *rparam = NULL;
    2041          10 :         uint32_t num_rparam = 0;
    2042          10 :         uint8_t *rdata = NULL;
    2043          10 :         uint32_t num_rdata = 0;
    2044          10 :         uint16_t num_names_returned = 0;
    2045          10 :         struct file_info *finfo = NULL;
    2046          10 :         uint8_t *p2 = NULL;
    2047          10 :         uint8_t *data_end = NULL;
    2048          10 :         uint16_t i = 0;
    2049             : 
    2050          10 :         PUSH_LE_U16(&setup[0], 0, TRANSACT2_FINDFIRST);
    2051             : 
    2052          10 :         param = talloc_array(mem_ctx, uint8_t, 12);
    2053          10 :         if (param == NULL) {
    2054           0 :                 return NT_STATUS_NO_MEMORY;
    2055             :         }
    2056             : 
    2057          10 :         PUSH_LE_U16(param, 0, FILE_ATTRIBUTE_DIRECTORY |
    2058             :                 FILE_ATTRIBUTE_SYSTEM |
    2059             :                 FILE_ATTRIBUTE_HIDDEN);
    2060          10 :         PUSH_LE_U16(param, 2, 1366); /* max_matches */
    2061          10 :         PUSH_LE_U16(param, 4, FLAG_TRANS2_FIND_CLOSE_IF_END);
    2062          10 :         PUSH_LE_U16(param, 6, SMB_FIND_FILE_BOTH_DIRECTORY_INFO); /* info_level */
    2063             : 
    2064          10 :         param = trans2_bytes_push_str(param,
    2065          10 :                                       smbXcli_conn_use_unicode(cli->conn),
    2066             :                                       search_name,
    2067          10 :                                       strlen(search_name)+1,
    2068             :                                       NULL);
    2069          10 :         if (param == NULL) {
    2070           0 :                 return NT_STATUS_NO_MEMORY;
    2071             :         }
    2072             : 
    2073             :         /*
    2074             :          * A one shot SMB1 findfirst will be enough to
    2075             :          * return ".", "..", and "file".
    2076             :          */
    2077          10 :         status = cli_trans(mem_ctx,
    2078             :                            cli,
    2079             :                            SMBtrans2, /* cmd */
    2080             :                            NULL, /* pipe_name */
    2081             :                            0, /* fid */
    2082             :                            0, /* function */
    2083             :                            0, /* flags */
    2084             :                            &setup[0],
    2085             :                            1, /* num_setup uint16_t words */
    2086             :                            0, /* max returned setup */
    2087             :                            param,
    2088          10 :                            talloc_get_size(param), /* num_param */
    2089             :                            10, /* max returned param */
    2090             :                            NULL, /* data */
    2091             :                            0, /* num_data */
    2092             :                            SMB_BUFFER_SIZE_MAX, /* max returned data */
    2093             :                            /* Return values from here on.. */
    2094             :                            &recv_flags2, /* recv_flags2 */
    2095             :                            NULL, /* rsetup */
    2096             :                            0, /* min returned rsetup */
    2097             :                            NULL, /* num_rsetup */
    2098             :                            &rparam,
    2099             :                            6, /* min returned rparam */
    2100             :                            &num_rparam, /* number of returned rparam */
    2101             :                            &rdata,
    2102             :                            0, /* min returned rdata */
    2103             :                            &num_rdata);
    2104          10 :         if (!NT_STATUS_IS_OK(status)) {
    2105           0 :                 return status;
    2106             :         }
    2107             : 
    2108          10 :         num_names_returned = PULL_LE_U16(rparam, 2);
    2109             : 
    2110          10 :         finfo = talloc_array(mem_ctx, struct file_info, num_names_returned);
    2111          10 :         if (param == NULL) {
    2112           0 :                 return NT_STATUS_NO_MEMORY;
    2113             :         }
    2114             : 
    2115          10 :         p2 = rdata;
    2116          10 :         data_end = rdata + num_rdata;
    2117             : 
    2118          40 :         for (i = 0; i < num_names_returned; i++) {
    2119          30 :                 if (p2 >= data_end) {
    2120           0 :                         break;
    2121             :                 }
    2122          30 :                 if (i == num_names_returned - 1) {
    2123             :                         /* Last entry - fixup the last offset length. */
    2124          10 :                         PUSH_LE_U32(p2, 0, PTR_DIFF((rdata + num_rdata), p2));
    2125             :                 }
    2126             : 
    2127          60 :                 p2 += get_filename(mem_ctx,
    2128             :                                    cli,
    2129             :                                    rdata,
    2130             :                                    recv_flags2,
    2131             :                                    p2,
    2132             :                                    data_end,
    2133          30 :                                    &finfo[i]);
    2134             : 
    2135          30 :                 if (finfo->name == NULL) {
    2136           0 :                         printf("%s:%d Unable to parse name from listing "
    2137             :                                 "of %s, position %u\n",
    2138             :                                 __FILE__,
    2139             :                                 __LINE__,
    2140             :                                 search_name,
    2141             :                                 (unsigned int)i);
    2142           0 :                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
    2143             :                 }
    2144             :         }
    2145          10 :         *num_names = i;
    2146          10 :         *names = finfo;
    2147          10 :         return NT_STATUS_OK;
    2148             : }
    2149             : 
    2150             : /*
    2151             :  * Test a specific SMB1 findfirst path to see if it
    2152             :  * matches a given file array.
    2153             :  */
    2154           8 : static bool test_smb1_findfirst_path(struct cli_state *cli,
    2155             :                                      const char *search_path,
    2156             :                                      struct file_info *root_finfo,
    2157             :                                      size_t num_root_finfo)
    2158             : {
    2159           8 :         size_t i = 0;
    2160           8 :         size_t num_finfo = 0;
    2161           8 :         struct file_info *finfo = NULL;
    2162           0 :         NTSTATUS status;
    2163             : 
    2164           8 :         status = smb1_findfirst(talloc_tos(),
    2165             :                                 cli,
    2166             :                                 search_path,
    2167             :                                 &finfo,
    2168             :                                 &num_finfo);
    2169           8 :         if (!NT_STATUS_IS_OK(status)) {
    2170           0 :                 printf("%s:%d smb1findfirst on %s returned %s\n",
    2171             :                         __FILE__,
    2172             :                         __LINE__,
    2173             :                         search_path,
    2174             :                         nt_errstr(status));
    2175           0 :                 return false;
    2176             :         }
    2177             : 
    2178           8 :         if (num_finfo != num_root_finfo) {
    2179           0 :                 printf("%s:%d On %s, num_finfo = %zu, num_root_finfo = %zu\n",
    2180             :                         __FILE__,
    2181             :                         __LINE__,
    2182             :                         search_path,
    2183             :                         num_finfo,
    2184             :                         num_root_finfo);
    2185           0 :                 return false;
    2186             :         }
    2187          32 :         for (i = 0; i < num_finfo; i++) {
    2188          24 :                 bool match = strequal_m(finfo[i].name,
    2189          24 :                                         root_finfo[i].name);
    2190          24 :                 if (!match) {
    2191           0 :                         printf("%s:%d Mismatch. For %s, at position %zu, "
    2192             :                                "finfo[i].name = %s, "
    2193             :                                "root_finfo[i].name = %s\n",
    2194             :                                 __FILE__,
    2195             :                                 __LINE__,
    2196             :                                 search_path,
    2197             :                                 i,
    2198           0 :                                 finfo[i].name,
    2199           0 :                                 root_finfo[i].name);
    2200           0 :                         return false;
    2201             :                 }
    2202             :         }
    2203           8 :         TALLOC_FREE(finfo);
    2204           8 :         return true;
    2205             : }
    2206             : 
    2207             : /*
    2208             :  * "Raw" test of doing a SMB1 findfirst to a DFS share.
    2209             :  * We must (mostly) use the lower level smb1cli_XXXX() interfaces,
    2210             :  * not the cli_XXX() ones here as the ultimate goal is to fix our
    2211             :  * cli_XXX() interfaces to work transparently over DFS.
    2212             :  *
    2213             :  * So here, we're testing the server code, not the client code.
    2214             :  *
    2215             :  * Passes cleanly against Windows.
    2216             :  */
    2217             : 
    2218           2 : bool run_smb1_dfs_search_paths(int dummy)
    2219             : {
    2220           2 :         struct cli_state *cli = NULL;
    2221           0 :         NTSTATUS status;
    2222           2 :         bool dfs_supported = false;
    2223           2 :         struct file_info *root_finfo = NULL;
    2224           2 :         size_t num_root_finfo = 0;
    2225           2 :         bool retval = false;
    2226           2 :         bool ok = false;
    2227           2 :         uint16_t fnum = (uint16_t)-1;
    2228             : 
    2229           2 :         printf("Starting SMB1-DFS-SEARCH-PATHS\n");
    2230             : 
    2231           2 :         if (!torture_init_connection(&cli)) {
    2232           0 :                 return false;
    2233             :         }
    2234             : 
    2235           2 :         if (!torture_open_connection(&cli, 0)) {
    2236           0 :                 return false;
    2237             :         }
    2238             : 
    2239             :         /* Ensure this is a DFS share. */
    2240           2 :         dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
    2241           2 :         if (!dfs_supported) {
    2242           0 :                 printf("Server %s does not support DFS\n",
    2243           0 :                         smbXcli_conn_remote_name(cli->conn));
    2244           0 :                 return false;
    2245             :         }
    2246           2 :         dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb1.tcon);
    2247           2 :         if (!dfs_supported) {
    2248           0 :                 printf("Share %s does not support DFS\n",
    2249           0 :                         cli->share);
    2250           0 :                 return false;
    2251             :         }
    2252             : 
    2253             :         /* Start clean. */
    2254           2 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\file");
    2255             : 
    2256             :         /* Create a test file to search for. */
    2257           2 :         status = smb1cli_ntcreatex(cli->conn,
    2258           2 :                                    cli->timeout,
    2259           2 :                                    cli->smb1.pid,
    2260           2 :                                    cli->smb1.tcon,
    2261           2 :                                    cli->smb1.session,
    2262             :                                    "BAD\\BAD\\file",
    2263             :                                    OPLOCK_NONE, /* CreatFlags */
    2264             :                                    0, /* RootDirectoryFid */
    2265             :                                    SEC_STD_SYNCHRONIZE|
    2266             :                                         SEC_STD_DELETE |
    2267             :                                         SEC_FILE_READ_DATA|
    2268             :                                         SEC_FILE_READ_ATTRIBUTE, /* DesiredAccess */
    2269             :                                    0, /* AllocationSize */
    2270             :                                    FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
    2271             :                                    FILE_SHARE_READ|
    2272             :                                         FILE_SHARE_WRITE|
    2273             :                                         FILE_SHARE_DELETE, /* ShareAccess */
    2274             :                                    FILE_CREATE, /* CreateDisposition */
    2275             :                                    0, /* CreateOptions */
    2276             :                                    2, /* ImpersonationLevel */
    2277             :                                    0, /* SecurityFlags */
    2278             :                                    &fnum);
    2279           2 :         if (!NT_STATUS_IS_OK(status)) {
    2280           0 :                 printf("%s:%d smb1cli_ntcreatex on %s returned %s\n",
    2281             :                         __FILE__,
    2282             :                         __LINE__,
    2283             :                         "BAD\\BAD\\file",
    2284             :                         nt_errstr(status));
    2285           0 :                 return false;
    2286             :         }
    2287             : 
    2288             :         /* Close "file" handle. */
    2289           2 :         (void)smb1cli_close(cli->conn,
    2290           2 :                             cli->timeout,
    2291           2 :                             cli->smb1.pid,
    2292           2 :                             cli->smb1.tcon,
    2293           2 :                             cli->smb1.session,
    2294             :                             fnum,
    2295             :                             0); /* last_modified */
    2296           2 :         fnum = (uint16_t)-1;
    2297             : 
    2298             :         /* Get the list of files in the share. */
    2299           2 :         status = smb1_findfirst(talloc_tos(),
    2300             :                                 cli,
    2301             :                                 "SERVER\\SHARE\\*",
    2302             :                                 &root_finfo,
    2303             :                                 &num_root_finfo);
    2304           2 :         if (!NT_STATUS_IS_OK(status)) {
    2305           0 :                 printf("%s:%d smb1findfirst on %s returned %s\n",
    2306             :                         __FILE__,
    2307             :                         __LINE__,
    2308             :                         "SERVER\\SHARE\\*",
    2309             :                         nt_errstr(status));
    2310           0 :                 return false;
    2311             :         }
    2312             : 
    2313             :         /*
    2314             :          * Try different search names. They should
    2315             :          * all match the root directory list.
    2316             :          */
    2317           2 :         ok = test_smb1_findfirst_path(cli,
    2318             :                                       "\\SERVER\\SHARE\\*",
    2319             :                                       root_finfo,
    2320             :                                       num_root_finfo);
    2321           2 :         if (!ok) {
    2322           0 :                 goto err;
    2323             :         }
    2324             : 
    2325           2 :         ok = test_smb1_findfirst_path(cli,
    2326             :                                       "*",
    2327             :                                       root_finfo,
    2328             :                                       num_root_finfo);
    2329           2 :         if (!ok) {
    2330           0 :                 goto err;
    2331             :         }
    2332           2 :         ok = test_smb1_findfirst_path(cli,
    2333             :                                       "\\*",
    2334             :                                       root_finfo,
    2335             :                                       num_root_finfo);
    2336           2 :         if (!ok) {
    2337           0 :                 goto err;
    2338             :         }
    2339           2 :         ok = test_smb1_findfirst_path(cli,
    2340             :                                       "\\SERVER\\*",
    2341             :                                       root_finfo,
    2342             :                                       num_root_finfo);
    2343           2 :         if (!ok) {
    2344           0 :                 goto err;
    2345             :         }
    2346           2 :         retval = true;
    2347             : 
    2348           2 :   err:
    2349             : 
    2350           2 :         if (fnum != (uint16_t)-1) {
    2351           0 :                 (void)smb1cli_close(cli->conn,
    2352           0 :                                     cli->timeout,
    2353           0 :                                     cli->smb1.pid,
    2354           0 :                                     cli->smb1.tcon,
    2355           0 :                                     cli->smb1.session,
    2356             :                                     fnum,
    2357             :                                     0); /* last_modified */
    2358             :         }
    2359             : 
    2360             :         /* Delete anything we made. */
    2361           2 :         (void)smb1_dfs_delete(cli, "BAD\\BAD\\file");
    2362           2 :         return retval;
    2363             : }
    2364             : 
    2365           4 : static bool smb1_create_testfile(struct cli_state *cli,
    2366             :                                  const char *path)
    2367             : {
    2368           0 :         NTSTATUS status;
    2369           4 :         uint16_t fnum = (uint16_t)-1;
    2370             : 
    2371             :         /* Create a test file. */
    2372           4 :         status = smb1cli_ntcreatex(cli->conn,
    2373           4 :                                    cli->timeout,
    2374             :                                    cli->smb1.pid,
    2375             :                                    cli->smb1.tcon,
    2376             :                                    cli->smb1.session,
    2377             :                                    path,
    2378             :                                    OPLOCK_NONE, /* CreatFlags */
    2379             :                                    0, /* RootDirectoryFid */
    2380             :                                    SEC_STD_SYNCHRONIZE|
    2381             :                                         SEC_STD_DELETE |
    2382             :                                         SEC_FILE_READ_DATA|
    2383             :                                         SEC_FILE_READ_ATTRIBUTE, /* DesiredAccess */
    2384             :                                    0, /* AllocationSize */
    2385             :                                    FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
    2386             :                                    FILE_SHARE_READ|
    2387             :                                         FILE_SHARE_WRITE|
    2388             :                                         FILE_SHARE_DELETE, /* ShareAccess */
    2389             :                                    FILE_CREATE, /* CreateDisposition */
    2390             :                                    0, /* CreateOptions */
    2391             :                                    2, /* ImpersonationLevel */
    2392             :                                    0, /* SecurityFlags */
    2393             :                                    &fnum);
    2394           4 :         if (!NT_STATUS_IS_OK(status)) {
    2395           0 :                 printf("%s:%d smb1cli_ntcreatex on %s returned %s\n",
    2396             :                         __FILE__,
    2397             :                         __LINE__,
    2398             :                         path,
    2399             :                         nt_errstr(status));
    2400           0 :                 return false;
    2401             :         }
    2402             : 
    2403             :         /* Close "file" handle. */
    2404           4 :         (void)smb1cli_close(cli->conn,
    2405           4 :                             cli->timeout,
    2406             :                             cli->smb1.pid,
    2407             :                             cli->smb1.tcon,
    2408             :                             cli->smb1.session,
    2409             :                             fnum,
    2410             :                             0); /* last_modified */
    2411           4 :         return true;
    2412             : }
    2413             : 
    2414           6 : static NTSTATUS smb1_unlink(struct cli_state *cli,
    2415             :                             const char *path)
    2416             : {
    2417           0 :         uint16_t vwv[1];
    2418           6 :         uint8_t *bytes = NULL;
    2419             : 
    2420           6 :         PUSH_LE_U16(vwv, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
    2421           6 :         bytes = talloc_array(talloc_tos(), uint8_t, 1);
    2422           6 :         if (bytes == NULL) {
    2423           0 :                 return NT_STATUS_NO_MEMORY;
    2424             :         }
    2425           6 :         bytes[0] = 4;
    2426           6 :         bytes = smb_bytes_push_str(bytes,
    2427           6 :                                    smbXcli_conn_use_unicode(cli->conn),
    2428             :                                    path,
    2429           6 :                                    strlen(path)+1,
    2430             :                                    NULL);
    2431           6 :         if (bytes == NULL) {
    2432           0 :                 return NT_STATUS_NO_MEMORY;
    2433             :         }
    2434             : 
    2435           6 :         return cli_smb(talloc_tos(),
    2436             :                        cli,
    2437             :                        SMBunlink, /* command. */
    2438             :                        0, /* additional_flags. */
    2439             :                        1, /* wct. */
    2440             :                        vwv, /* vwv. */
    2441           6 :                        talloc_get_size(bytes), /* num_bytes. */
    2442             :                        bytes, /* bytes. */
    2443             :                        NULL, /* result parent. */
    2444             :                        0, /* min_wct. */
    2445             :                        NULL, /* return wcount. */
    2446             :                        NULL, /* return wvw. */
    2447             :                        NULL, /* return byte count. */
    2448             :                        NULL); /* return bytes. */
    2449             : }
    2450             : 
    2451           2 : static bool test_smb1_unlink(struct cli_state *cli)
    2452             : {
    2453           0 :         NTSTATUS status;
    2454           2 :         bool retval = false;
    2455           2 :         bool ok = false;
    2456             : 
    2457             :         /* Start clean. */
    2458           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\file");
    2459             : 
    2460             :         /* Create a test file. */
    2461           2 :         ok = smb1_create_testfile(cli, "\\BAD\\BAD\\file");
    2462           2 :         if (!ok) {
    2463           0 :                 printf("%s:%d failed to create test file %s\n",
    2464             :                         __FILE__,
    2465             :                         __LINE__,
    2466             :                         "\\BAD\\BAD\\file");
    2467           0 :                 goto err;
    2468             :         }
    2469             : 
    2470           2 :         status = smb1_unlink(cli, "file");
    2471           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    2472           0 :                 printf("%s:%d SMB1unlink of %s should get "
    2473             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    2474             :                         __FILE__,
    2475             :                         __LINE__,
    2476             :                         "file",
    2477             :                         nt_errstr(status));
    2478           0 :                 goto err;
    2479             :         }
    2480           2 :         status = smb1_unlink(cli, "\\BAD\\file");
    2481           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    2482           0 :                 printf("%s:%d SMB1unlink of %s should get "
    2483             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    2484             :                         __FILE__,
    2485             :                         __LINE__,
    2486             :                         "\\BAD\\file",
    2487             :                         nt_errstr(status));
    2488           0 :                 goto err;
    2489             :         }
    2490           2 :         status = smb1_unlink(cli, "\\BAD\\BAD\\file");
    2491           2 :         if (!NT_STATUS_IS_OK(status)) {
    2492           0 :                 printf("%s:%d SMB1unlink on %s returned %s\n",
    2493             :                         __FILE__,
    2494             :                         __LINE__,
    2495             :                         "\\BAD\\BAD\\file",
    2496             :                         nt_errstr(status));
    2497           0 :                 goto err;
    2498             :         }
    2499             : 
    2500           2 :         retval = true;
    2501             : 
    2502           2 :   err:
    2503             : 
    2504           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\file");
    2505           2 :         return retval;
    2506             : }
    2507             : 
    2508           8 : static NTSTATUS smb1_mkdir(struct cli_state *cli,
    2509             :                            const char *path)
    2510             : {
    2511           8 :         uint8_t *bytes = NULL;
    2512             : 
    2513           8 :         bytes = talloc_array(talloc_tos(), uint8_t, 1);
    2514           8 :         if (bytes == NULL) {
    2515           0 :                 return NT_STATUS_NO_MEMORY;
    2516             :         }
    2517           8 :         bytes[0] = 4;
    2518           8 :         bytes = smb_bytes_push_str(bytes,
    2519           8 :                                    smbXcli_conn_use_unicode(cli->conn),
    2520             :                                    path,
    2521           8 :                                    strlen(path)+1,
    2522             :                                    NULL);
    2523           8 :         if (bytes == NULL) {
    2524           0 :                 return NT_STATUS_NO_MEMORY;
    2525             :         }
    2526             : 
    2527           8 :         return cli_smb(talloc_tos(),
    2528             :                        cli,
    2529             :                        SMBmkdir, /* command. */
    2530             :                        0, /* additional_flags. */
    2531             :                        0, /* wct. */
    2532             :                        NULL, /* vwv. */
    2533           8 :                        talloc_get_size(bytes), /* num_bytes. */
    2534             :                        bytes, /* bytes. */
    2535             :                        NULL, /* result parent. */
    2536             :                        0, /* min_wct. */
    2537             :                        NULL, /* return wcount. */
    2538             :                        NULL, /* return wvw. */
    2539             :                        NULL, /* return byte count. */
    2540             :                        NULL); /* return bytes. */
    2541             : }
    2542             : 
    2543           2 : static bool test_smb1_mkdir(struct cli_state *cli)
    2544             : {
    2545           0 :         NTSTATUS status;
    2546           2 :         bool retval = false;
    2547             : 
    2548             :         /* Start clean. */
    2549           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\dir");
    2550             : 
    2551           2 :         status = smb1_mkdir(cli, "dir");
    2552           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
    2553           0 :                 printf("%s:%d SMB1mkdir of %s should get "
    2554             :                         "NT_STATUS_OBJECT_NAME_COLLISION, got %s\n",
    2555             :                         __FILE__,
    2556             :                         __LINE__,
    2557             :                         "dir",
    2558             :                         nt_errstr(status));
    2559           0 :                 goto err;
    2560             :         }
    2561           2 :         status = smb1_mkdir(cli, "\\BAD\\dir");
    2562           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
    2563           0 :                 printf("%s:%d SMB1mkdir of %s should get "
    2564             :                         "NT_STATUS_OBJECT_NAME_COLLISION, got %s\n",
    2565             :                         __FILE__,
    2566             :                         __LINE__,
    2567             :                         "\\BAD\\dir",
    2568             :                         nt_errstr(status));
    2569           0 :                 goto err;
    2570             :         }
    2571           2 :         status = smb1_mkdir(cli, "\\BAD\\BAD\\dir");
    2572           2 :         if (!NT_STATUS_IS_OK(status)) {
    2573           0 :                 printf("%s:%d SMB1mkdir on %s returned %s\n",
    2574             :                         __FILE__,
    2575             :                         __LINE__,
    2576             :                         "\\BAD\\BAD\\dir",
    2577             :                         nt_errstr(status));
    2578           0 :                 goto err;
    2579             :         }
    2580             : 
    2581           2 :         retval = true;
    2582             : 
    2583           2 :   err:
    2584             : 
    2585           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\dir");
    2586           2 :         return retval;
    2587             : }
    2588             : 
    2589           6 : static NTSTATUS smb1_rmdir(struct cli_state *cli,
    2590             :                            const char *path)
    2591             : {
    2592           6 :         uint8_t *bytes = NULL;
    2593             : 
    2594           6 :         bytes = talloc_array(talloc_tos(), uint8_t, 1);
    2595           6 :         if (bytes == NULL) {
    2596           0 :                 return NT_STATUS_NO_MEMORY;
    2597             :         }
    2598           6 :         bytes[0] = 4;
    2599           6 :         bytes = smb_bytes_push_str(bytes,
    2600           6 :                                    smbXcli_conn_use_unicode(cli->conn),
    2601             :                                    path,
    2602           6 :                                    strlen(path)+1,
    2603             :                                    NULL);
    2604           6 :         if (bytes == NULL) {
    2605           0 :                 return NT_STATUS_NO_MEMORY;
    2606             :         }
    2607             : 
    2608           6 :         return cli_smb(talloc_tos(),
    2609             :                        cli,
    2610             :                        SMBrmdir, /* command. */
    2611             :                        0, /* additional_flags. */
    2612             :                        0, /* wct. */
    2613             :                        NULL, /* vwv. */
    2614           6 :                        talloc_get_size(bytes), /* num_bytes. */
    2615             :                        bytes, /* bytes. */
    2616             :                        NULL, /* result parent. */
    2617             :                        0, /* min_wct. */
    2618             :                        NULL, /* return wcount. */
    2619             :                        NULL, /* return wvw. */
    2620             :                        NULL, /* return byte count. */
    2621             :                        NULL); /* return bytes. */
    2622             : }
    2623             : 
    2624           2 : static bool test_smb1_rmdir(struct cli_state *cli)
    2625             : {
    2626           0 :         NTSTATUS status;
    2627           2 :         bool retval = false;
    2628             : 
    2629             :         /* Start clean. */
    2630           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\dir");
    2631             : 
    2632           2 :         status = smb1_mkdir(cli, "\\BAD\\BAD\\dir");
    2633           2 :         if (!NT_STATUS_IS_OK(status)) {
    2634           0 :                 printf("%s:%d SMB1rmdir on %s returned %s\n",
    2635             :                         __FILE__,
    2636             :                         __LINE__,
    2637             :                         "\\BAD\\BAD\\dir",
    2638             :                         nt_errstr(status));
    2639           0 :                 goto err;
    2640             :         }
    2641             : 
    2642           2 :         status = smb1_rmdir(cli, "dir");
    2643           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
    2644           0 :                 printf("%s:%d SMB1rmdir of %s should get "
    2645             :                         "NT_STATUS_ACCESS_DENIED, got %s\n",
    2646             :                         __FILE__,
    2647             :                         __LINE__,
    2648             :                         "dir",
    2649             :                         nt_errstr(status));
    2650           0 :                 goto err;
    2651             :         }
    2652           2 :         status = smb1_rmdir(cli, "\\BAD\\dir");
    2653           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
    2654           0 :                 printf("%s:%d SMB1rmdir of %s should get "
    2655             :                         "NT_STATUS_ACCESS_DENIED, got %s\n",
    2656             :                         __FILE__,
    2657             :                         __LINE__,
    2658             :                         "\\BAD\\dir",
    2659             :                         nt_errstr(status));
    2660           0 :                 goto err;
    2661             :         }
    2662           2 :         status = smb1_rmdir(cli, "\\BAD\\BAD\\dir");
    2663           2 :         if (!NT_STATUS_IS_OK(status)) {
    2664           0 :                 printf("%s:%d SMB1rmdir on %s returned %s\n",
    2665             :                         __FILE__,
    2666             :                         __LINE__,
    2667             :                         "\\BAD\\BAD\\dir",
    2668             :                         nt_errstr(status));
    2669           0 :                 goto err;
    2670             :         }
    2671             : 
    2672           2 :         retval = true;
    2673             : 
    2674           2 :   err:
    2675             : 
    2676           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\dir");
    2677           2 :         return retval;
    2678             : }
    2679             : 
    2680           6 : static NTSTATUS smb1_ntcreatex(struct cli_state *cli,
    2681             :                                const char *path)
    2682             : {
    2683           0 :         NTSTATUS status;
    2684           6 :         uint16_t fnum = (uint16_t)-1;
    2685             : 
    2686           6 :         status = smb1cli_ntcreatex(cli->conn,
    2687           6 :                                    cli->timeout,
    2688             :                                    cli->smb1.pid,
    2689             :                                    cli->smb1.tcon,
    2690             :                                    cli->smb1.session,
    2691             :                                    path,
    2692             :                                    OPLOCK_NONE, /* CreatFlags */
    2693             :                                    0, /* RootDirectoryFid */
    2694             :                                    SEC_STD_SYNCHRONIZE|
    2695             :                                         SEC_STD_DELETE |
    2696             :                                         SEC_FILE_READ_DATA|
    2697             :                                         SEC_FILE_READ_ATTRIBUTE, /* DesiredAccess */
    2698             :                                    0, /* AllocationSize */
    2699             :                                    FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
    2700             :                                    FILE_SHARE_READ|
    2701             :                                         FILE_SHARE_WRITE|
    2702             :                                         FILE_SHARE_DELETE, /* ShareAccess */
    2703             :                                    FILE_CREATE, /* CreateDisposition */
    2704             :                                    0, /* CreateOptions */
    2705             :                                    2, /* ImpersonationLevel */
    2706             :                                    0, /* SecurityFlags */
    2707             :                                    &fnum);
    2708           6 :         if (!NT_STATUS_IS_OK(status)) {
    2709           4 :                 return status;
    2710             :         }
    2711             : 
    2712             :         /* Close "file" handle. */
    2713           2 :         (void)smb1cli_close(cli->conn,
    2714           2 :                             cli->timeout,
    2715             :                             cli->smb1.pid,
    2716             :                             cli->smb1.tcon,
    2717             :                             cli->smb1.session,
    2718             :                             fnum,
    2719             :                             0); /* last_modified */
    2720           2 :         return NT_STATUS_OK;
    2721             : }
    2722             : 
    2723           2 : static bool test_smb1_ntcreatex(struct cli_state *cli)
    2724             : {
    2725           0 :         NTSTATUS status;
    2726           2 :         bool retval = false;
    2727             : 
    2728             :         /* Start clean. */
    2729           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\ntcreateXfile");
    2730             : 
    2731           2 :         status = smb1_ntcreatex(cli, "ntcreateXfile");
    2732           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
    2733           0 :                 printf("%s:%d SMB1ntcreateX of %s should get "
    2734             :                         "NT_STATUS_OBJECT_NAME_COLLISION, got %s\n",
    2735             :                         __FILE__,
    2736             :                         __LINE__,
    2737             :                         "ntcreateXfile",
    2738             :                         nt_errstr(status));
    2739           0 :                 goto err;
    2740             :         }
    2741           2 :         status = smb1_ntcreatex(cli, "\\BAD\\ntcreateXfile");
    2742           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
    2743           0 :                 printf("%s:%d SMB1ntcreateX of %s should get "
    2744             :                         "NT_STATUS_OBJECT_NAME_COLLISION, got %s\n",
    2745             :                         __FILE__,
    2746             :                         __LINE__,
    2747             :                         "\\BAD\\ntcreateXfile",
    2748             :                         nt_errstr(status));
    2749           0 :                 goto err;
    2750             :         }
    2751           2 :         status = smb1_ntcreatex(cli, "\\BAD\\BAD\\ntcreateXfile");
    2752           2 :         if (!NT_STATUS_IS_OK(status)) {
    2753           0 :                 printf("%s:%d SMB1ntcreateX on %s returned %s\n",
    2754             :                         __FILE__,
    2755             :                         __LINE__,
    2756             :                         "\\BAD\\BAD\\ntcreateXfile",
    2757             :                         nt_errstr(status));
    2758           0 :                 goto err;
    2759             :         }
    2760             : 
    2761           2 :         retval = true;
    2762             : 
    2763           2 :   err:
    2764             : 
    2765           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\ntcreateXfile");
    2766           2 :         return retval;
    2767             : }
    2768             : 
    2769           6 : static NTSTATUS smb1_nttrans_create(struct cli_state *cli,
    2770             :                                     const char *path)
    2771             : {
    2772           6 :         uint8_t *param = NULL;
    2773           6 :         size_t converted_len = 0;
    2774           6 :         uint8_t *rparam = NULL;
    2775           6 :         uint32_t num_rparam = 0;
    2776           6 :         uint16_t fnum = (uint16_t)-1;
    2777           0 :         NTSTATUS status;
    2778             : 
    2779           6 :         param = talloc_zero_array(talloc_tos(), uint8_t, 53);
    2780           6 :         if (param == NULL) {
    2781           0 :                 return NT_STATUS_NO_MEMORY;
    2782             :         }
    2783             : 
    2784           6 :         param = trans2_bytes_push_str(param,
    2785           6 :                                       smbXcli_conn_use_unicode(cli->conn),
    2786             :                                       path,
    2787             :                                       strlen(path),
    2788             :                                       &converted_len);
    2789           6 :         if (param == NULL) {
    2790           0 :                 return NT_STATUS_NO_MEMORY;
    2791             :         }
    2792             : 
    2793           6 :         PUSH_LE_U32(param, 8, SEC_STD_SYNCHRONIZE|
    2794             :                                 SEC_STD_DELETE |
    2795             :                                 SEC_FILE_READ_DATA|
    2796             :                                 SEC_FILE_READ_ATTRIBUTE); /* DesiredAccess */
    2797           6 :         PUSH_LE_U32(param, 20, FILE_ATTRIBUTE_NORMAL);
    2798           6 :         PUSH_LE_U32(param, 24, FILE_SHARE_READ|
    2799             :                                 FILE_SHARE_WRITE|
    2800             :                                 FILE_SHARE_DELETE); /* ShareAccess */
    2801           6 :         PUSH_LE_U32(param, 28, FILE_CREATE);
    2802           6 :         PUSH_LE_U32(param, 44, converted_len);
    2803           6 :         PUSH_LE_U32(param, 48, 0x02); /* ImpersonationLevel */
    2804             : 
    2805           6 :         status = cli_trans(talloc_tos(),
    2806             :                            cli,
    2807             :                            SMBnttrans, /* trans cmd */
    2808             :                            NULL, /* pipe_name */
    2809             :                            0, /* fid */
    2810             :                            NT_TRANSACT_CREATE, /* function */
    2811             :                            0, /* flags */
    2812             :                            NULL, /* setup */
    2813             :                            0, /* num_setup */
    2814             :                            0, /* max_setup */
    2815             :                            param, /* param */
    2816           6 :                            talloc_get_size(param), /* num_param */
    2817             :                            128, /* max_param */
    2818             :                            NULL, /* data */
    2819             :                            0, /* num_data */
    2820             :                            0, /* max_data */
    2821             :                            NULL, /* recv_flags2 */
    2822             :                            NULL, /* rsetup */
    2823             :                            0, /* min_rsetup */
    2824             :                            NULL, /* num_rsetup */
    2825             :                            &rparam, /* rparam */
    2826             :                            69, /* min_rparam */
    2827             :                            &num_rparam, /* num_rparam */
    2828             :                            NULL, /* rdata */
    2829             :                            0, /* min_rdata */
    2830             :                            NULL); /* num_rdata */
    2831           6 :         if (!NT_STATUS_IS_OK(status)) {
    2832           4 :                 return status;
    2833             :         }
    2834           2 :         fnum = PULL_LE_U16(param, 2);
    2835             :         /* Close "file" handle. */
    2836           2 :         (void)smb1cli_close(cli->conn,
    2837           2 :                             cli->timeout,
    2838             :                             cli->smb1.pid,
    2839             :                             cli->smb1.tcon,
    2840             :                             cli->smb1.session,
    2841             :                             fnum,
    2842             :                             0); /* last_modified */
    2843           2 :         return NT_STATUS_OK;
    2844             : }
    2845             : 
    2846           2 : static bool test_smb1_nttrans_create(struct cli_state *cli)
    2847             : {
    2848           0 :         NTSTATUS status;
    2849           2 :         bool retval = false;
    2850             : 
    2851             :         /* Start clean. */
    2852           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\nttransfile");
    2853             : 
    2854           2 :         status = smb1_nttrans_create(cli, "nttransfile");
    2855           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
    2856           0 :                 printf("%s:%d SMB1trans NT_TRANSACT_CREATE of %s should get "
    2857             :                         "NT_STATUS_OBJECT_NAME_COLLISION, got %s\n",
    2858             :                         __FILE__,
    2859             :                         __LINE__,
    2860             :                         "nttransfile",
    2861             :                         nt_errstr(status));
    2862           0 :                 goto err;
    2863             :         }
    2864           2 :         status = smb1_nttrans_create(cli, "\\BAD\\nttransfile");
    2865           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
    2866           0 :                 printf("%s:%d SMB1trans NT_TRANSACT_CREATE of %s should get "
    2867             :                         "NT_STATUS_OBJECT_NAME_COLLISION, got %s\n",
    2868             :                         __FILE__,
    2869             :                         __LINE__,
    2870             :                         "\\BAD\\nttransfile",
    2871             :                         nt_errstr(status));
    2872           0 :                 goto err;
    2873             :         }
    2874           2 :         status = smb1_nttrans_create(cli, "\\BAD\\BAD\\nttransfile");
    2875           2 :         if (!NT_STATUS_IS_OK(status)) {
    2876           0 :                 printf("%s:%d SMB1trans NT_TRANSACT_CREATE on %s returned %s\n",
    2877             :                         __FILE__,
    2878             :                         __LINE__,
    2879             :                         "\\BAD\\BAD\\nttransfile",
    2880             :                         nt_errstr(status));
    2881           0 :                 goto err;
    2882             :         }
    2883             : 
    2884           2 :         retval = true;
    2885             : 
    2886           2 :   err:
    2887             : 
    2888           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\nttransfile");
    2889           2 :         return retval;
    2890             : }
    2891             : 
    2892             : struct smb1_openx_state {
    2893             :         const char *fname;
    2894             :         uint16_t vwv[15];
    2895             :         uint16_t fnum;
    2896             :         struct iovec bytes;
    2897             : };
    2898             : 
    2899             : static void smb1_openx_done(struct tevent_req *subreq);
    2900             : 
    2901           6 : static struct tevent_req *smb1_openx_send(TALLOC_CTX *mem_ctx,
    2902             :                                           struct tevent_context *ev,
    2903             :                                           struct cli_state *cli,
    2904             :                                           const char *path)
    2905             : {
    2906           6 :         struct tevent_req *req = NULL;
    2907           6 :         struct tevent_req *subreq = NULL;
    2908           6 :         uint16_t accessmode = 0;
    2909           6 :         struct smb1_openx_state *state = NULL;
    2910           6 :         uint8_t *bytes = NULL;
    2911           0 :         NTSTATUS status;
    2912             : 
    2913           6 :         req = tevent_req_create(mem_ctx, &state, struct smb1_openx_state);
    2914           6 :         if (req == NULL) {
    2915           0 :                 return NULL;
    2916             :         }
    2917             : 
    2918           6 :         accessmode = (DENY_NONE<<4);
    2919           6 :         accessmode |= DOS_OPEN_RDONLY;
    2920             : 
    2921           6 :         PUSH_LE_U8(state->vwv + 0, 0, 0xFF);
    2922           6 :         PUSH_LE_U16(state->vwv + 3, 0, accessmode);
    2923           6 :         PUSH_LE_U16(state->vwv + 4, 0,
    2924             :                 FILE_ATTRIBUTE_SYSTEM |
    2925             :                 FILE_ATTRIBUTE_HIDDEN |
    2926             :                 FILE_ATTRIBUTE_DIRECTORY);
    2927           6 :         PUSH_LE_U16(state->vwv + 8,
    2928             :                 0,
    2929             :                 OPENX_FILE_CREATE_IF_NOT_EXIST| OPENX_FILE_EXISTS_FAIL);
    2930             : 
    2931           6 :         bytes = talloc_array(state, uint8_t, 0);
    2932           6 :         if (tevent_req_nomem(bytes, req)) {
    2933           0 :                 return tevent_req_post(req, ev);
    2934             :         }
    2935           6 :         bytes = smb_bytes_push_str(bytes,
    2936           6 :                                    smbXcli_conn_use_unicode(cli->conn),
    2937             :                                    path,
    2938           6 :                                    strlen(path)+1,
    2939             :                                    NULL);
    2940           6 :         if (tevent_req_nomem(bytes, req)) {
    2941           0 :                 return tevent_req_post(req, ev);
    2942             :         }
    2943             : 
    2944           6 :         state->bytes.iov_base = (void *)bytes;
    2945           6 :         state->bytes.iov_len = talloc_get_size(bytes);
    2946          12 :         subreq = cli_smb_req_create(state,
    2947             :                                     ev,
    2948             :                                     cli,
    2949             :                                     SMBopenX, /* cmd */
    2950             :                                     0, /* additional_flags */
    2951             :                                     0, /* additional_flags2 */
    2952             :                                     15, /* num_vwv */
    2953           6 :                                     state->vwv, /* vwv */
    2954             :                                     1, /* iovcount */
    2955           6 :                                     &state->bytes); /* iovec */
    2956           6 :         if (tevent_req_nomem(subreq, req)) {
    2957           0 :                 return tevent_req_post(req, ev);
    2958             :         }
    2959           6 :         tevent_req_set_callback(subreq, smb1_openx_done, req);
    2960             : 
    2961           6 :         status = smb1cli_req_chain_submit(&subreq, 1);
    2962           6 :         if (tevent_req_nterror(req, status)) {
    2963           0 :                 return tevent_req_post(req, ev);
    2964             :         }
    2965           6 :         return req;
    2966             : }
    2967             : 
    2968           6 : static void smb1_openx_done(struct tevent_req *subreq)
    2969             : {
    2970           6 :         struct tevent_req *req = tevent_req_callback_data(
    2971             :                 subreq, struct tevent_req);
    2972           6 :         struct smb1_openx_state *state = tevent_req_data(
    2973             :                 req, struct smb1_openx_state);
    2974           6 :         uint8_t wct = 0;
    2975           6 :         uint16_t *vwv = NULL;
    2976           0 :         NTSTATUS status;
    2977             : 
    2978           6 :         status = cli_smb_recv(subreq,
    2979             :                               state,
    2980             :                               NULL, /* pinbuf */
    2981             :                               3, /* min_wct */
    2982             :                               &wct, /* wct */
    2983             :                               &vwv, /* vwv */
    2984             :                               NULL, /* num_rbytes */
    2985             :                               NULL); /* rbytes */
    2986           6 :         TALLOC_FREE(subreq);
    2987           6 :         if (tevent_req_nterror(req, status)) {
    2988           4 :                 return;
    2989             :         }
    2990           2 :         state->fnum = PULL_LE_U16(vwv+2, 0);
    2991           2 :         tevent_req_done(req);
    2992             : }
    2993             : 
    2994           6 : static NTSTATUS smb1_openx_recv(struct tevent_req *req, uint16_t *pfnum)
    2995             : {
    2996           6 :         struct smb1_openx_state *state = tevent_req_data(
    2997             :                 req, struct smb1_openx_state);
    2998           0 :         NTSTATUS status;
    2999             : 
    3000           6 :         if (tevent_req_is_nterror(req, &status)) {
    3001           4 :                 return status;
    3002             :         }
    3003           2 :         *pfnum = state->fnum;
    3004           2 :         return NT_STATUS_OK;
    3005             : }
    3006             : 
    3007           6 : static NTSTATUS smb1_openx(struct cli_state *cli, const char *path)
    3008             : {
    3009           6 :         TALLOC_CTX *frame = talloc_stackframe();
    3010           6 :         struct tevent_context *ev = NULL;
    3011           6 :         struct tevent_req *req = NULL;
    3012           6 :         uint16_t fnum = (uint16_t)-1;
    3013           6 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3014             : 
    3015           6 :         ev = samba_tevent_context_init(frame);
    3016           6 :         if (ev == NULL) {
    3017           0 :                 goto fail;
    3018             :         }
    3019             : 
    3020           6 :         req = smb1_openx_send(frame,
    3021             :                               ev,
    3022             :                               cli,
    3023             :                               path);
    3024           6 :         if (req == NULL) {
    3025           0 :                 goto fail;
    3026             :         }
    3027             : 
    3028           6 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3029           0 :                 goto fail;
    3030             :         }
    3031             : 
    3032           6 :         status = smb1_openx_recv(req, &fnum);
    3033           6 :  fail:
    3034             : 
    3035             :         /* Close "file" handle. */
    3036           6 :         if (fnum != (uint16_t)-1) {
    3037           2 :                 (void)smb1cli_close(cli->conn,
    3038           2 :                                     cli->timeout,
    3039             :                                     cli->smb1.pid,
    3040             :                                     cli->smb1.tcon,
    3041             :                                     cli->smb1.session,
    3042             :                                     fnum,
    3043             :                                     0); /* last_modified */
    3044             :         }
    3045           6 :         TALLOC_FREE(frame);
    3046           6 :         return status;
    3047             : }
    3048             : 
    3049           2 : static bool test_smb1_openx(struct cli_state *cli)
    3050             : {
    3051           0 :         NTSTATUS status;
    3052           2 :         bool retval = false;
    3053             : 
    3054             :         /* Start clean. */
    3055           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\openxfile");
    3056             : 
    3057           2 :         status = smb1_openx(cli, "openxfile");
    3058           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3059           0 :                 printf("%s:%d SMB1openx of %s should get "
    3060             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3061             :                         __FILE__,
    3062             :                         __LINE__,
    3063             :                         "openxfile",
    3064             :                         nt_errstr(status));
    3065           0 :                 goto err;
    3066             :         }
    3067           2 :         status = smb1_openx(cli, "\\BAD\\openxfile");
    3068           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3069           0 :                 printf("%s:%d SMB1openx of %s should get "
    3070             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3071             :                         __FILE__,
    3072             :                         __LINE__,
    3073             :                         "\\BAD\\openxfile",
    3074             :                         nt_errstr(status));
    3075           0 :                 goto err;
    3076             :         }
    3077           2 :         status = smb1_openx(cli, "\\BAD\\BAD\\openxfile");
    3078           2 :         if (!NT_STATUS_IS_OK(status)) {
    3079           0 :                 printf("%s:%d SMB1openx on %s returned %s\n",
    3080             :                         __FILE__,
    3081             :                         __LINE__,
    3082             :                         "\\BAD\\BAD\\openxfile",
    3083             :                         nt_errstr(status));
    3084           0 :                 goto err;
    3085             :         }
    3086             : 
    3087           2 :         retval = true;
    3088             : 
    3089           2 :   err:
    3090             : 
    3091           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\openxfile");
    3092           2 :         return retval;
    3093             : }
    3094             : 
    3095           6 : static NTSTATUS smb1_open(struct cli_state *cli,
    3096             :                           const char *path,
    3097             :                           uint16_t *pfnum)
    3098             : {
    3099           6 :         uint16_t vwv[2] = { 0, 0};
    3100           6 :         uint8_t *bytes = NULL;
    3101           6 :         uint16_t accessmode = 0;
    3102           6 :         uint16_t *return_words = NULL;
    3103           6 :         uint8_t return_wcount = 0;
    3104           0 :         NTSTATUS status;
    3105             : 
    3106           6 :         accessmode = (DENY_NONE<<4);
    3107           6 :         accessmode |= DOS_OPEN_RDONLY;
    3108             : 
    3109           6 :         PUSH_LE_U16(vwv + 0, 0, accessmode);
    3110           6 :         PUSH_LE_U16(vwv + 1, 0, FILE_ATTRIBUTE_NORMAL);
    3111             : 
    3112           6 :         bytes = talloc_array(talloc_tos(), uint8_t, 1);
    3113           6 :         if (bytes == NULL) {
    3114           0 :                 return NT_STATUS_NO_MEMORY;
    3115             :         }
    3116           6 :         bytes[0] = 4;
    3117           6 :         bytes = smb_bytes_push_str(bytes,
    3118           6 :                                    smbXcli_conn_use_unicode(cli->conn),
    3119             :                                    path,
    3120           6 :                                    strlen(path)+1,
    3121             :                                    NULL);
    3122           6 :         if (bytes == NULL) {
    3123           0 :                 return NT_STATUS_NO_MEMORY;
    3124             :         }
    3125             : 
    3126           6 :         status = cli_smb(talloc_tos(),
    3127             :                          cli,
    3128             :                          SMBopen, /* command. */
    3129             :                          0, /* additional_flags. */
    3130             :                          2, /* wct. */
    3131             :                          vwv, /* vwv. */
    3132           6 :                          talloc_get_size(bytes), /* num_bytes. */
    3133             :                          bytes, /* bytes. */
    3134             :                          NULL, /* result parent. */
    3135             :                          7, /* min_wct. */
    3136             :                          &return_wcount, /* return wcount. */
    3137             :                          &return_words, /* return wvw. */
    3138             :                          NULL, /* return byte count. */
    3139             :                          NULL); /* return bytes. */
    3140           6 :         if (!NT_STATUS_IS_OK(status)) {
    3141           4 :                 return status;
    3142             :         }
    3143           2 :         *pfnum = PULL_LE_U16(return_words, 0);
    3144           2 :         return status;
    3145             : }
    3146             : 
    3147           2 : static bool test_smb1_open(struct cli_state *cli)
    3148             : {
    3149           0 :         NTSTATUS status;
    3150           2 :         bool retval = false;
    3151           2 :         bool ok = false;
    3152           2 :         bool equal = false;
    3153           2 :         uint16_t fnum = (uint16_t)-1;
    3154           2 :         struct timespec testfile_crtime = { 0 };
    3155           2 :         struct timespec open_crtime = { 0 };
    3156             : 
    3157             :         /* Start clean. */
    3158           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\openfile");
    3159             : 
    3160             :         /* Create a test file. */
    3161           2 :         ok = smb1_create_testfile(cli, "\\BAD\\BAD\\openfile");
    3162           2 :         if (!ok) {
    3163           0 :                 printf("%s:%d failed to create test file %s\n",
    3164             :                         __FILE__,
    3165             :                         __LINE__,
    3166             :                         "\\BAD\\BAD\\openfile");
    3167           0 :                 goto err;
    3168             :         }
    3169             : 
    3170             :         /* Get the test file crtime number. */
    3171           2 :         status = get_smb1_crtime(cli,
    3172             :                                 "\\BAD\\BAD\\openfile",
    3173             :                                 &testfile_crtime);
    3174           2 :         if (!NT_STATUS_IS_OK(status)) {
    3175           0 :                 printf("%s:%d Failed to get crtime for %s, (%s)\n",
    3176             :                         __FILE__,
    3177             :                         __LINE__,
    3178             :                         "\\BAD\\BAD\\openfile",
    3179             :                         nt_errstr(status));
    3180           0 :                 goto err;
    3181             :         }
    3182             : 
    3183           2 :         status = smb1_open(cli, "openfile", &fnum);
    3184           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3185           0 :                 printf("%s:%d SMB1open of %s should get "
    3186             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3187             :                         __FILE__,
    3188             :                         __LINE__,
    3189             :                         "openfile",
    3190             :                         nt_errstr(status));
    3191           0 :                 goto err;
    3192             :         }
    3193           2 :         status = smb1_open(cli, "\\BAD\\openfile", &fnum);
    3194           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3195           0 :                 printf("%s:%d SMB1open of %s should get "
    3196             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3197             :                         __FILE__,
    3198             :                         __LINE__,
    3199             :                         "\\BAD\\openfile",
    3200             :                         nt_errstr(status));
    3201           0 :                 goto err;
    3202             :         }
    3203           2 :         status = smb1_open(cli, "\\BAD\\BAD\\openfile", &fnum);
    3204           2 :         if (!NT_STATUS_IS_OK(status)) {
    3205           0 :                 printf("%s:%d failed to open test file %s (%s)\n",
    3206             :                         __FILE__,
    3207             :                         __LINE__,
    3208             :                         "\\BAD\\BAD\\openfile",
    3209             :                         nt_errstr(status));
    3210           0 :                 goto err;
    3211             :         }
    3212             : 
    3213           2 :         status = cli_qfileinfo_basic(cli,
    3214             :                                      fnum,
    3215             :                                      NULL, /* attr */
    3216             :                                      NULL, /* size */
    3217             :                                      &open_crtime, /* create_time */
    3218             :                                      NULL, /* access_time */
    3219             :                                      NULL, /* write_time */
    3220             :                                      NULL, /* change_time */
    3221             :                                      NULL); /* ino */
    3222           2 :         if (!NT_STATUS_IS_OK(status)) {
    3223           0 :                 printf("%s:%d failed to get crtime of test file %s (%s)\n",
    3224             :                         __FILE__,
    3225             :                         __LINE__,
    3226             :                         "\\BAD\\BAD\\openfile",
    3227             :                         nt_errstr(status));
    3228           0 :                 goto err;
    3229             :         }
    3230           2 :         equal = (timespec_compare(&testfile_crtime, &open_crtime) == 0);
    3231           2 :         if (!equal) {
    3232           0 :                 printf("%s:%d crtime mismatch of test file %s\n",
    3233             :                         __FILE__,
    3234             :                         __LINE__,
    3235             :                         "\\BAD\\BAD\\openfile");
    3236           0 :                 goto err;
    3237             :         }
    3238             : 
    3239           2 :         retval = true;
    3240             : 
    3241           2 :   err:
    3242             : 
    3243             :         /* Close "openfile" handle. */
    3244           2 :         if (fnum != (uint16_t)-1) {
    3245           2 :                 (void)smb1cli_close(cli->conn,
    3246           2 :                                     cli->timeout,
    3247             :                                     cli->smb1.pid,
    3248             :                                     cli->smb1.tcon,
    3249             :                                     cli->smb1.session,
    3250             :                                     fnum,
    3251             :                                     0); /* last_modified */
    3252             :         }
    3253           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\openfile");
    3254           2 :         return retval;
    3255             : }
    3256             : 
    3257           2 : static NTSTATUS smb1_create(struct cli_state *cli,
    3258             :                             const char *path,
    3259             :                             uint16_t smb1_operation,
    3260             :                             uint16_t *pfnum)
    3261             : {
    3262           2 :         uint16_t vwv[3] = { 0, 0, 0};
    3263           2 :         uint8_t *bytes = NULL;
    3264           2 :         uint16_t *return_words = NULL;
    3265           2 :         uint8_t return_wcount = 0;
    3266           0 :         NTSTATUS status;
    3267             : 
    3268           2 :         PUSH_LE_U16(vwv + 0, 0, FILE_ATTRIBUTE_NORMAL);
    3269             : 
    3270           2 :         bytes = talloc_array(talloc_tos(), uint8_t, 1);
    3271           2 :         if (bytes == NULL) {
    3272           0 :                 return NT_STATUS_NO_MEMORY;
    3273             :         }
    3274           2 :         bytes[0] = 4;
    3275           2 :         bytes = smb_bytes_push_str(bytes,
    3276           2 :                                    smbXcli_conn_use_unicode(cli->conn),
    3277             :                                    path,
    3278           2 :                                    strlen(path)+1,
    3279             :                                    NULL);
    3280           2 :         if (bytes == NULL) {
    3281           0 :                 return NT_STATUS_NO_MEMORY;
    3282             :         }
    3283             : 
    3284           2 :         status = cli_smb(talloc_tos(),
    3285             :                          cli,
    3286             :                          smb1_operation, /* command. */
    3287             :                          0, /* additional_flags. */
    3288             :                          3, /* wct. */
    3289             :                          vwv, /* vwv. */
    3290           2 :                          talloc_get_size(bytes), /* num_bytes. */
    3291             :                          bytes, /* bytes. */
    3292             :                          NULL, /* result parent. */
    3293             :                          1, /* min_wct. */
    3294             :                          &return_wcount, /* return wcount. */
    3295             :                          &return_words, /* return wvw. */
    3296             :                          NULL, /* return byte count. */
    3297             :                          NULL); /* return bytes. */
    3298           2 :         if (!NT_STATUS_IS_OK(status)) {
    3299           2 :                 return status;
    3300             :         }
    3301           0 :         *pfnum = PULL_LE_U16(return_words, 0);
    3302           0 :         return status;
    3303             : }
    3304             : 
    3305           2 : static bool test_smb1_create(struct cli_state *cli)
    3306             : {
    3307           0 :         NTSTATUS status;
    3308           2 :         bool retval = false;
    3309           2 :         uint16_t fnum = (uint16_t)-1;
    3310             : 
    3311             :         /* Start clean. */
    3312           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\createfile");
    3313           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\mknewfile");
    3314             : 
    3315           2 :         status = smb1_create(cli, "createfile", SMBcreate, &fnum);
    3316           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3317           2 :                 printf("%s:%d SMB1create of %s should get "
    3318             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3319             :                         __FILE__,
    3320             :                         __LINE__,
    3321             :                         "createfile",
    3322             :                         nt_errstr(status));
    3323           2 :                 goto err;
    3324             :         }
    3325           0 :         status = smb1_create(cli, "\\BAD\\createfile", SMBcreate, &fnum);
    3326           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3327           0 :                 printf("%s:%d SMB1open of %s should get "
    3328             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3329             :                         __FILE__,
    3330             :                         __LINE__,
    3331             :                         "\\BAD\\openfile",
    3332             :                         nt_errstr(status));
    3333           0 :                 goto err;
    3334             :         }
    3335           0 :         status = smb1_create(cli, "\\BAD\\BAD\\createfile", SMBcreate, &fnum);
    3336           0 :         if (!NT_STATUS_IS_OK(status)) {
    3337           0 :                 printf("%s:%d failed to create file %s (%s)\n",
    3338             :                         __FILE__,
    3339             :                         __LINE__,
    3340             :                         "\\BAD\\BAD\\createfile",
    3341             :                         nt_errstr(status));
    3342           0 :                 goto err;
    3343             :         }
    3344             : 
    3345           0 :         (void)smb1cli_close(cli->conn,
    3346           0 :                             cli->timeout,
    3347             :                             cli->smb1.pid,
    3348             :                             cli->smb1.tcon,
    3349             :                             cli->smb1.session,
    3350             :                             fnum,
    3351             :                             0); /* last_modified */
    3352             : 
    3353           0 :         fnum = (uint16_t)-1;
    3354             : 
    3355             :         /* Now do the same with SMBmknew */
    3356           0 :         status = smb1_create(cli, "mknewfile", SMBmknew, &fnum);
    3357           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3358           0 :                 printf("%s:%d SMB1mknew of %s should get "
    3359             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3360             :                         __FILE__,
    3361             :                         __LINE__,
    3362             :                         "mknewfile",
    3363             :                         nt_errstr(status));
    3364           0 :                 goto err;
    3365             :         }
    3366           0 :         status = smb1_create(cli, "\\BAD\\mknewfile", SMBmknew, &fnum);
    3367           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3368           0 :                 printf("%s:%d SMB1mknew of %s should get "
    3369             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3370             :                         __FILE__,
    3371             :                         __LINE__,
    3372             :                         "\\BAD\\mknewfile",
    3373             :                         nt_errstr(status));
    3374           0 :                 goto err;
    3375             :         }
    3376           0 :         status = smb1_create(cli, "\\BAD\\BAD\\mknewfile", SMBmknew, &fnum);
    3377           0 :         if (!NT_STATUS_IS_OK(status)) {
    3378           0 :                 printf("%s:%d failed to create file %s (%s)\n",
    3379             :                         __FILE__,
    3380             :                         __LINE__,
    3381             :                         "\\BAD\\BAD\\mknewfile",
    3382             :                         nt_errstr(status));
    3383           0 :                 goto err;
    3384             :         }
    3385             : 
    3386           0 :         (void)smb1cli_close(cli->conn,
    3387           0 :                             cli->timeout,
    3388             :                             cli->smb1.pid,
    3389             :                             cli->smb1.tcon,
    3390             :                             cli->smb1.session,
    3391             :                             fnum,
    3392             :                             0); /* last_modified */
    3393             : 
    3394           0 :         fnum = (uint16_t)-1;
    3395             : 
    3396           0 :         retval = true;
    3397             : 
    3398           2 :   err:
    3399             : 
    3400             :         /* Close "openfile" handle. */
    3401           2 :         if (fnum != (uint16_t)-1) {
    3402           0 :                 (void)smb1cli_close(cli->conn,
    3403           0 :                                     cli->timeout,
    3404             :                                     cli->smb1.pid,
    3405             :                                     cli->smb1.tcon,
    3406             :                                     cli->smb1.session,
    3407             :                                     fnum,
    3408             :                                     0); /* last_modified */
    3409             :         }
    3410           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\createfile");
    3411           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\mknewfile");
    3412           2 :         return retval;
    3413             : }
    3414             : 
    3415           0 : static NTSTATUS smb1_getatr(struct cli_state *cli,
    3416             :                             const char *path,
    3417             :                             uint16_t *pattr)
    3418             : {
    3419           0 :         uint8_t *bytes = NULL;
    3420           0 :         uint16_t *return_words = NULL;
    3421           0 :         uint8_t return_wcount = 0;
    3422           0 :         NTSTATUS status;
    3423             : 
    3424           0 :         bytes = talloc_array(talloc_tos(), uint8_t, 1);
    3425           0 :         if (bytes == NULL) {
    3426           0 :                 return NT_STATUS_NO_MEMORY;
    3427             :         }
    3428           0 :         bytes[0] = 4;
    3429           0 :         bytes = smb_bytes_push_str(bytes,
    3430           0 :                                    smbXcli_conn_use_unicode(cli->conn),
    3431             :                                    path,
    3432           0 :                                    strlen(path)+1,
    3433             :                                    NULL);
    3434           0 :         if (bytes == NULL) {
    3435           0 :                 return NT_STATUS_NO_MEMORY;
    3436             :         }
    3437             : 
    3438           0 :         status = cli_smb(talloc_tos(),
    3439             :                          cli,
    3440             :                          SMBgetatr, /* command. */
    3441             :                          0, /* additional_flags. */
    3442             :                          0, /* wct. */
    3443             :                          NULL, /* vwv. */
    3444           0 :                          talloc_get_size(bytes), /* num_bytes. */
    3445             :                          bytes, /* bytes. */
    3446             :                          NULL, /* result parent. */
    3447             :                          10, /* min_wct. */
    3448             :                          &return_wcount, /* return wcount. */
    3449             :                          &return_words, /* return wvw. */
    3450             :                          NULL, /* return byte count. */
    3451             :                          NULL); /* return bytes. */
    3452           0 :         if (!NT_STATUS_IS_OK(status)) {
    3453           0 :                 return status;
    3454             :         }
    3455           0 :         *pattr = PULL_LE_U16(return_words, 0);
    3456           0 :         return status;
    3457             : }
    3458             : 
    3459           0 : static bool test_smb1_getatr(struct cli_state *cli)
    3460             : {
    3461           0 :         NTSTATUS status;
    3462           0 :         bool retval = false;
    3463           0 :         bool ok = false;
    3464           0 :         uint16_t attrs = 0;
    3465             : 
    3466             :         /* Start clean. */
    3467           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\getatrfile");
    3468             : 
    3469             :         /* Create a test file. */
    3470           0 :         ok = smb1_create_testfile(cli, "\\BAD\\BAD\\getatrfile");
    3471           0 :         if (!ok) {
    3472           0 :                 printf("%s:%d failed to create test file %s\n",
    3473             :                         __FILE__,
    3474             :                         __LINE__,
    3475             :                         "\\BAD\\BAD\\getatrfile");
    3476           0 :                 goto err;
    3477             :         }
    3478             : 
    3479             :         /*
    3480             :          * We expect this to succeed, but get attributes of
    3481             :          * the root directory.
    3482             :          */
    3483           0 :         status = smb1_getatr(cli, "getatrfile", &attrs);
    3484           0 :         if (!NT_STATUS_IS_OK(status)) {
    3485           0 :                 printf("%s:%d SMB1getatr of %s failed (%s)\n",
    3486             :                         __FILE__,
    3487             :                         __LINE__,
    3488             :                         "getatrfile",
    3489             :                         nt_errstr(status));
    3490           0 :                 goto err;
    3491             :         }
    3492           0 :         if ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0) {
    3493           0 :                 printf("%s:%d error expected SMB1getatr of file %s "
    3494             :                         "to return directory attributes. Got 0x%x\n",
    3495             :                         __FILE__,
    3496             :                         __LINE__,
    3497             :                         "getatrfile",
    3498             :                         (unsigned int)attrs);
    3499           0 :                 goto err;
    3500             :         }
    3501             : 
    3502             :         /*
    3503             :          * We expect this to succeed, but get attributes of
    3504             :          * the root directory.
    3505             :          */
    3506           0 :         status = smb1_getatr(cli, "\\BAD\\getatrfile", &attrs);
    3507           0 :         if (!NT_STATUS_IS_OK(status)) {
    3508           0 :                 printf("%s:%d SMB1getatr of %s failed (%s)\n",
    3509             :                         __FILE__,
    3510             :                         __LINE__,
    3511             :                         "\\BAD\\getatrfile",
    3512             :                         nt_errstr(status));
    3513           0 :                 goto err;
    3514             :         }
    3515           0 :         if ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0) {
    3516           0 :                 printf("%s:%d error expected SMB1getatr of file %s "
    3517             :                         "to return directory attributes. Got 0x%x\n",
    3518             :                         __FILE__,
    3519             :                         __LINE__,
    3520             :                         "\\BAD\\getatrfile",
    3521             :                         (unsigned int)attrs);
    3522           0 :                 goto err;
    3523             :         }
    3524             : 
    3525             :         /*
    3526             :          * We expect this to succeed, and get attributes of
    3527             :          * the testfile.
    3528             :          */
    3529           0 :         status = smb1_getatr(cli, "\\BAD\\BAD\\getatrfile", &attrs);
    3530           0 :         if (!NT_STATUS_IS_OK(status)) {
    3531           0 :                 printf("%s:%d SMB1getatr of %s failed (%s)\n",
    3532             :                         __FILE__,
    3533             :                         __LINE__,
    3534             :                         "\\BAD\\BAD\\getatrfile",
    3535             :                         nt_errstr(status));
    3536           0 :                 goto err;
    3537             :         }
    3538           0 :         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
    3539           0 :                 printf("%s:%d error expected SMB1getatr of file %s "
    3540             :                         "to return non-directory attributes. Got 0x%x\n",
    3541             :                         __FILE__,
    3542             :                         __LINE__,
    3543             :                         "\\BAD\\BAD\\getatrfile",
    3544             :                         (unsigned int)attrs);
    3545           0 :                 goto err;
    3546             :         }
    3547             : 
    3548           0 :         retval = true;
    3549             : 
    3550           0 :   err:
    3551             : 
    3552           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\getatrfile");
    3553           0 :         return retval;
    3554             : }
    3555             : 
    3556           0 : static NTSTATUS smb1_setatr(struct cli_state *cli,
    3557             :                             const char *path,
    3558             :                             uint16_t attr)
    3559             : {
    3560           0 :         uint16_t vwv[8] = { 0 };
    3561           0 :         uint8_t *bytes = NULL;
    3562           0 :         NTSTATUS status;
    3563             : 
    3564           0 :         PUSH_LE_U16(vwv, 0, attr);
    3565           0 :         bytes = talloc_array(talloc_tos(), uint8_t, 1);
    3566           0 :         if (bytes == NULL) {
    3567           0 :                 return NT_STATUS_NO_MEMORY;
    3568             :         }
    3569           0 :         bytes[0] = 4;
    3570           0 :         bytes = smb_bytes_push_str(bytes,
    3571           0 :                                    smbXcli_conn_use_unicode(cli->conn),
    3572             :                                    path,
    3573           0 :                                    strlen(path)+1,
    3574             :                                    NULL);
    3575           0 :         if (bytes == NULL) {
    3576           0 :                 return NT_STATUS_NO_MEMORY;
    3577             :         }
    3578           0 :         status = cli_smb(talloc_tos(),
    3579             :                          cli,
    3580             :                          SMBsetatr, /* command. */
    3581             :                          0, /* additional_flags. */
    3582             :                          8, /* wct. */
    3583             :                          vwv, /* vwv. */
    3584           0 :                          talloc_get_size(bytes), /* num_bytes. */
    3585             :                          bytes, /* bytes. */
    3586             :                          NULL, /* result parent. */
    3587             :                          0, /* min_wct. */
    3588             :                          NULL, /* return wcount. */
    3589             :                          NULL, /* return wvw. */
    3590             :                          NULL, /* return byte count. */
    3591             :                          NULL); /* return bytes. */
    3592           0 :         if (!NT_STATUS_IS_OK(status)) {
    3593           0 :                 return status;
    3594             :         }
    3595           0 :         return status;
    3596             : }
    3597             : 
    3598           0 : static bool test_smb1_setatr(struct cli_state *cli)
    3599             : {
    3600           0 :         NTSTATUS status;
    3601           0 :         bool retval = false;
    3602           0 :         bool ok = false;
    3603           0 :         uint16_t file_attrs = 0;
    3604           0 :         uint16_t orig_file_attrs = 0;
    3605             : 
    3606             :         /* Start clean. */
    3607           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\setatrfile");
    3608             : 
    3609             :         /* Create a test file. */
    3610           0 :         ok = smb1_create_testfile(cli, "\\BAD\\BAD\\setatrfile");
    3611           0 :         if (!ok) {
    3612           0 :                 printf("%s:%d failed to create test file %s\n",
    3613             :                         __FILE__,
    3614             :                         __LINE__,
    3615             :                         "\\BAD\\BAD\\setatrfile");
    3616           0 :                 goto err;
    3617             :         }
    3618             :         /* Get it's original attributes. */
    3619           0 :         status = smb1_getatr(cli, "\\BAD\\BAD\\setatrfile", &orig_file_attrs);
    3620           0 :         if (!NT_STATUS_IS_OK(status)) {
    3621           0 :                 printf("%s:%d SMB1getatr of %s failed (%s)\n",
    3622             :                         __FILE__,
    3623             :                         __LINE__,
    3624             :                         "\\BAD\\BAD\\setatrfile",
    3625             :                         nt_errstr(status));
    3626           0 :                 goto err;
    3627             :         }
    3628             : 
    3629           0 :         if (orig_file_attrs & FILE_ATTRIBUTE_SYSTEM) {
    3630           0 :                 printf("%s:%d orig_file_attrs of %s already has SYSTEM. "
    3631             :                         "Test cannot proceed.\n",
    3632             :                         __FILE__,
    3633             :                         __LINE__,
    3634             :                         "\\BAD\\BAD\\setatrfile");
    3635           0 :                 goto err;
    3636             :         }
    3637             : 
    3638             :         /*
    3639             :          * Seems we can't set attrs on the root of a share,
    3640             :          * even as Administrator.
    3641             :          */
    3642           0 :         status = smb1_setatr(cli, "setatrfile", FILE_ATTRIBUTE_SYSTEM);
    3643           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
    3644           0 :                 printf("%s:%d SMB1setatr of %s should get "
    3645             :                         "NT_STATUS_ACCESS_DENIED, got %s\n",
    3646             :                         __FILE__,
    3647             :                         __LINE__,
    3648             :                         "setatrfile",
    3649             :                         nt_errstr(status));
    3650           0 :                 goto err;
    3651             :         }
    3652             : 
    3653             :         /*
    3654             :          * Seems we can't set attrs on the root of a share,
    3655             :          * even as Administrator.
    3656             :          */
    3657           0 :         status = smb1_setatr(cli, "\\BAD\\setatrfile", FILE_ATTRIBUTE_SYSTEM);
    3658           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
    3659           0 :                 printf("%s:%d SMB1setatr of %s should get "
    3660             :                         "NT_STATUS_ACCESS_DENIED, got %s\n",
    3661             :                         __FILE__,
    3662             :                         __LINE__,
    3663             :                         "\\BAD\\setatrfile",
    3664             :                         nt_errstr(status));
    3665           0 :                 goto err;
    3666             :         }
    3667             : 
    3668           0 :         status = smb1_setatr(cli,
    3669             :                              "\\BAD\\BAD\\setatrfile",
    3670             :                              FILE_ATTRIBUTE_SYSTEM);
    3671           0 :         if (!NT_STATUS_IS_OK(status)) {
    3672           0 :                 printf("%s:%d SMB1setatr of %s failed (%s)\n",
    3673             :                         __FILE__,
    3674             :                         __LINE__,
    3675             :                         "\\BAD\\BAD\\setatrfile",
    3676             :                         nt_errstr(status));
    3677           0 :                 goto err;
    3678             :         }
    3679           0 :         status = smb1_getatr(cli, "\\BAD\\BAD\\setatrfile", &file_attrs);
    3680           0 :         if (!NT_STATUS_IS_OK(status)) {
    3681           0 :                 printf("%s:%d SMB1getatr of %s failed (%s)\n",
    3682             :                         __FILE__,
    3683             :                         __LINE__,
    3684             :                         "\\BAD\\BAD\\setatrfile",
    3685             :                         nt_errstr(status));
    3686           0 :                 goto err;
    3687             :         }
    3688             : 
    3689           0 :         if (file_attrs != FILE_ATTRIBUTE_SYSTEM) {
    3690           0 :                 printf("%s:%d Failed to set SYSTEM attr on %s\n",
    3691             :                         __FILE__,
    3692             :                         __LINE__,
    3693             :                         "\\BAD\\BAD\\setatrfile");
    3694           0 :                 goto err;
    3695             :         }
    3696             : 
    3697           0 :         retval = true;
    3698             : 
    3699           0 :   err:
    3700             : 
    3701           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\setatrfile");
    3702           0 :         return retval;
    3703             : }
    3704             : 
    3705           2 : static NTSTATUS smb1_chkpath(struct cli_state *cli,
    3706             :                              const char *path)
    3707             : {
    3708           2 :         uint8_t *bytes = NULL;
    3709           0 :         NTSTATUS status;
    3710             : 
    3711           2 :         bytes = talloc_array(talloc_tos(), uint8_t, 1);
    3712           2 :         if (bytes == NULL) {
    3713           0 :                 return NT_STATUS_NO_MEMORY;
    3714             :         }
    3715           2 :         bytes[0] = 4;
    3716           2 :         bytes = smb_bytes_push_str(bytes,
    3717           2 :                                    smbXcli_conn_use_unicode(cli->conn),
    3718             :                                    path,
    3719           2 :                                    strlen(path)+1,
    3720             :                                    NULL);
    3721           2 :         if (bytes == NULL) {
    3722           0 :                 return NT_STATUS_NO_MEMORY;
    3723             :         }
    3724           2 :         status = cli_smb(talloc_tos(),
    3725             :                          cli,
    3726             :                          SMBcheckpath, /* command. */
    3727             :                          0, /* additional_flags. */
    3728             :                          0, /* wct. */
    3729             :                          NULL, /* vwv. */
    3730           2 :                          talloc_get_size(bytes), /* num_bytes. */
    3731             :                          bytes, /* bytes. */
    3732             :                          NULL, /* result parent. */
    3733             :                          0, /* min_wct. */
    3734             :                          NULL, /* return wcount. */
    3735             :                          NULL, /* return wvw. */
    3736             :                          NULL, /* return byte count. */
    3737             :                          NULL); /* return bytes. */
    3738           2 :         if (!NT_STATUS_IS_OK(status)) {
    3739           0 :                 return status;
    3740             :         }
    3741           2 :         return status;
    3742             : }
    3743             : 
    3744           0 : static bool test_smb1_chkpath(struct cli_state *cli)
    3745             : {
    3746           0 :         NTSTATUS status;
    3747           0 :         bool retval = false;
    3748           0 :         bool ok = false;
    3749             : 
    3750             :         /* Start clean. */
    3751           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\chkpathfile");
    3752             : 
    3753             :         /* Create a test file. */
    3754           0 :         ok = smb1_create_testfile(cli, "\\BAD\\BAD\\chkpathfile");
    3755           0 :         if (!ok) {
    3756           0 :                 printf("%s:%d failed to create test file %s\n",
    3757             :                         __FILE__,
    3758             :                         __LINE__,
    3759             :                         "\\BAD\\BAD\\chkpathfile");
    3760           0 :                 goto err;
    3761             :         }
    3762             :         /*
    3763             :          * Should succeed - "chkpathfile" maps to
    3764             :          * directory "".
    3765             :          */
    3766           0 :         status = smb1_chkpath(cli, "chkpathfile");
    3767           0 :         if (!NT_STATUS_IS_OK(status)) {
    3768           0 :                 printf("%s:%d SMB1chkpath of %s failed (%s)\n",
    3769             :                         __FILE__,
    3770             :                         __LINE__,
    3771             :                         "chkpathfile",
    3772             :                         nt_errstr(status));
    3773           0 :                 goto err;
    3774             :         }
    3775             : 
    3776             :         /*
    3777             :          * Should succeed - "\\BAD\\chkpathfile" maps to
    3778             :          * directory "".
    3779             :          */
    3780           0 :         status = smb1_chkpath(cli, "\\BAD\\chkpathfile");
    3781           0 :         if (!NT_STATUS_IS_OK(status)) {
    3782           0 :                 printf("%s:%d SMB1chkpath of %s failed (%s)\n",
    3783             :                         __FILE__,
    3784             :                         __LINE__,
    3785             :                         "\\BAD\\chkpathfile",
    3786             :                         nt_errstr(status));
    3787           0 :                 goto err;
    3788             :         }
    3789             : 
    3790             :         /*
    3791             :          * Should fail - "\\BAD\\BAD\\chkpathfile" maps to the
    3792             :          * "\\BAD\\BAD\\chkpathfile", not a directory.
    3793             :          */
    3794           0 :         status = smb1_chkpath(cli, "\\BAD\\BAD\\chkpathfile");
    3795           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
    3796           0 :                 printf("%s:%d SMB1chkpath of %s should get "
    3797             :                         "NT_STATUS_NOT_A_DIRECTORY, got %s\n",
    3798             :                         __FILE__,
    3799             :                         __LINE__,
    3800             :                         "\\BAD\\BAD\\chkpathfile",
    3801             :                         nt_errstr(status));
    3802           0 :                 goto err;
    3803             :         }
    3804             : 
    3805           0 :         retval = true;
    3806             : 
    3807           0 :   err:
    3808             : 
    3809           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\chkpathfile");
    3810           0 :         return retval;
    3811             : }
    3812             : 
    3813             : /*
    3814             :  * Test BUG: https://bugzilla.samba.org/show_bug.cgi?id=15419
    3815             :  */
    3816             : 
    3817           2 : static bool test_smb1_chkpath_bad(struct cli_state *cli)
    3818             : {
    3819           0 :         NTSTATUS status;
    3820             : 
    3821           2 :         status = smb1_chkpath(cli, "\\x//\\/");
    3822           2 :         if (!NT_STATUS_IS_OK(status)) {
    3823           0 :                 printf("%s:%d SMB1chkpath of %s failed (%s)\n",
    3824             :                         __FILE__,
    3825             :                         __LINE__,
    3826             :                         "\\x//\\/",
    3827             :                         nt_errstr(status));
    3828           0 :                 return false;
    3829             :         }
    3830           2 :         return true;
    3831             : }
    3832             : 
    3833           0 : static NTSTATUS smb1_ctemp(struct cli_state *cli,
    3834             :                            const char *path,
    3835             :                            char **tmp_path)
    3836             : {
    3837           0 :         uint16_t vwv[3] = { 0 };
    3838           0 :         uint8_t *bytes = NULL;
    3839           0 :         NTSTATUS status;
    3840           0 :         uint16_t *return_words = NULL;
    3841           0 :         uint8_t return_wcount = 0;
    3842           0 :         uint32_t return_bytecount = 0;
    3843           0 :         uint8_t *return_bytes = NULL;
    3844           0 :         size_t sret = 0;
    3845           0 :         uint16_t fnum = (uint16_t)-1;
    3846             : 
    3847           0 :         bytes = talloc_array(talloc_tos(), uint8_t, 1);
    3848           0 :         if (bytes == NULL) {
    3849           0 :                 return NT_STATUS_NO_MEMORY;
    3850             :         }
    3851           0 :         bytes[0] = 4;
    3852           0 :         bytes = smb_bytes_push_str(bytes,
    3853           0 :                                    smbXcli_conn_use_unicode(cli->conn),
    3854             :                                    path,
    3855           0 :                                    strlen(path)+1,
    3856             :                                    NULL);
    3857           0 :         if (bytes == NULL) {
    3858           0 :                 return NT_STATUS_NO_MEMORY;
    3859             :         }
    3860           0 :         status = cli_smb(talloc_tos(),
    3861             :                          cli,
    3862             :                          SMBctemp, /* command. */
    3863             :                          0, /* additional_flags. */
    3864             :                          3, /* wct. */
    3865             :                          vwv, /* vwv. */
    3866           0 :                          talloc_get_size(bytes), /* num_bytes. */
    3867             :                          bytes, /* bytes. */
    3868             :                          NULL, /* result parent. */
    3869             :                          1, /* min_wct. */
    3870             :                          &return_wcount, /* return wcount. */
    3871             :                          &return_words, /* return wvw. */
    3872             :                          &return_bytecount, /* return byte count. */
    3873             :                          &return_bytes); /* return bytes. */
    3874           0 :         if (!NT_STATUS_IS_OK(status)) {
    3875           0 :                 return status;
    3876             :         }
    3877             : 
    3878           0 :         if (return_wcount != 1) {
    3879           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    3880             :         }
    3881             : 
    3882           0 :         fnum = PULL_LE_U16(return_words, 0);
    3883             : 
    3884             :         /* Delete the file by fnum. */
    3885           0 :         status = cli_nt_delete_on_close(cli, fnum, 1);
    3886           0 :         if (!NT_STATUS_IS_OK(status)) {
    3887           0 :                 return status;
    3888             :         }
    3889           0 :         (void)smb1cli_close(cli->conn,
    3890           0 :                             cli->timeout,
    3891             :                             cli->smb1.pid,
    3892             :                             cli->smb1.tcon,
    3893             :                             cli->smb1.session,
    3894             :                             fnum,
    3895             :                             0); /* last_modified */
    3896           0 :         fnum = (uint16_t)-1;
    3897             : 
    3898           0 :         if (return_bytecount < 2) {
    3899           0 :                 return NT_STATUS_DATA_ERROR;
    3900             :         }
    3901             : 
    3902           0 :         sret = pull_string_talloc(talloc_tos(),
    3903             :                                   NULL,
    3904             :                                   0,
    3905             :                                   tmp_path,
    3906             :                                   return_bytes,
    3907             :                                   return_bytecount,
    3908             :                                   STR_ASCII);
    3909           0 :         if (sret == 0) {
    3910           0 :                 return NT_STATUS_NO_MEMORY;
    3911             :         }
    3912             : 
    3913           0 :         return status;
    3914             : }
    3915             : 
    3916           0 : static bool test_smb1_ctemp(struct cli_state *cli)
    3917             : {
    3918           0 :         NTSTATUS status;
    3919           0 :         bool retval = false;
    3920           0 :         char *retpath = NULL;
    3921             : 
    3922             :         /* Start clean. */
    3923           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\ctemp_dir");
    3924             : 
    3925           0 :         status = smb1_mkdir(cli, "\\BAD\\BAD\\ctemp_dir");
    3926           0 :         if (!NT_STATUS_IS_OK(status)) {
    3927           0 :                 printf("%s:%d Failed to create %s (%s)\n",
    3928             :                         __FILE__,
    3929             :                         __LINE__,
    3930             :                         "\\BAD\\BAD\\ctemp_dir",
    3931             :                         nt_errstr(status));
    3932           0 :                 goto err;
    3933             :         }
    3934             : 
    3935             :         /*
    3936             :          * Windows returns NT_STATUS_FILE_IS_A_DIRECTORY
    3937             :          * for all SMBctemp calls on a DFS share, no
    3938             :          * matter what we put in the pathname.
    3939             :          */
    3940             : 
    3941             :         /*
    3942             :          * When we fix smbd we'll need to detect running
    3943             :          * in smbtorture3 against smbd here and modify
    3944             :          * the expected behavior. Windows is simply
    3945             :          * broken here.
    3946             :          */
    3947           0 :         status = smb1_ctemp(cli, "ctemp_dir", &retpath);
    3948           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3949           0 :                 printf("%s:%d SMB1ctemp of %s should get "
    3950             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3951             :                         __FILE__,
    3952             :                         __LINE__,
    3953             :                         "ctemp_dir",
    3954             :                         nt_errstr(status));
    3955           0 :                 goto err;
    3956             :         }
    3957           0 :         status = smb1_ctemp(cli, "\\BAD\\ctemp_dir", &retpath);
    3958           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3959           0 :                 printf("%s:%d SMB1ctemp of %s should get "
    3960             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3961             :                         __FILE__,
    3962             :                         __LINE__,
    3963             :                         "\\BAD\\ctemp_dir",
    3964             :                         nt_errstr(status));
    3965           0 :                 goto err;
    3966             :         }
    3967           0 :         status = smb1_ctemp(cli, "\\BAD\\BAD\\ctemp_dir", &retpath);
    3968           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
    3969           0 :                 printf("%s:%d SMB1ctemp of %s should get "
    3970             :                         "NT_STATUS_FILE_IS_A_DIRECTORY, got %s\n",
    3971             :                         __FILE__,
    3972             :                         __LINE__,
    3973             :                         "\\BAD\\BAD\\ctemp_dir",
    3974             :                         nt_errstr(status));
    3975           0 :                 goto err;
    3976             :         }
    3977             : 
    3978           0 :         retval = true;
    3979             : 
    3980           0 :   err:
    3981             : 
    3982           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\ctemp_dir");
    3983           0 :         return retval;
    3984             : }
    3985             : 
    3986           0 : static NTSTATUS smb1_qpathinfo(struct cli_state *cli,
    3987             :                                const char *fname,
    3988             :                                uint32_t *pattrs)
    3989             : {
    3990           0 :         NTSTATUS status;
    3991           0 :         uint8_t *param = NULL;
    3992           0 :         uint16_t setup[1] = { 0 };
    3993           0 :         uint8_t *rdata = NULL;
    3994           0 :         uint32_t num_rdata = 0;
    3995             : 
    3996           0 :         PUSH_LE_U16(setup, 0, TRANSACT2_QPATHINFO);
    3997             : 
    3998           0 :         param = talloc_zero_array(talloc_tos(), uint8_t, 6);
    3999           0 :         if (param == NULL) {
    4000           0 :                 return NT_STATUS_NO_MEMORY;
    4001             :         }
    4002           0 :         PUSH_LE_U16(param, 0, SMB_QUERY_FILE_BASIC_INFO);
    4003             : 
    4004           0 :         param = trans2_bytes_push_str(param,
    4005           0 :                                       smbXcli_conn_use_unicode(cli->conn),
    4006             :                                       fname,
    4007           0 :                                       strlen(fname)+1,
    4008             :                                       NULL);
    4009           0 :         if (param == NULL) {
    4010           0 :                 return NT_STATUS_NO_MEMORY;
    4011             :         }
    4012             : 
    4013           0 :         status = cli_trans(talloc_tos(),
    4014             :                            cli,
    4015             :                            SMBtrans2, /* cmd */
    4016             :                            NULL, /* pipe_name */
    4017             :                            0, /* fid */
    4018             :                            0, /* function */
    4019             :                            0, /* flags */
    4020             :                            &setup[0],
    4021             :                            1, /* num_setup uint16_t words */
    4022             :                            0, /* max returned setup */
    4023             :                            param,
    4024           0 :                            talloc_get_size(param), /* num_param */
    4025             :                            2, /* max returned param */
    4026             :                            NULL, /* data */
    4027             :                            0, /* num_data */
    4028             :                            SMB_BUFFER_SIZE_MAX, /* max returned data */
    4029             :                            /* Return values from here on.. */
    4030             :                            NULL, /* recv_flags2 */
    4031             :                            NULL, /* rsetup */
    4032             :                            0, /* min returned rsetup */
    4033             :                            NULL, /* num_rsetup */
    4034             :                            NULL,
    4035             :                            0, /* min returned rparam */
    4036             :                            NULL, /* number of returned rparam */
    4037             :                            &rdata,
    4038             :                            36, /* min returned rdata */
    4039             :                            &num_rdata);
    4040           0 :         if (!NT_STATUS_IS_OK(status)) {
    4041           0 :                 return status;
    4042             :         }
    4043           0 :         *pattrs = PULL_LE_U32(rdata, 32);
    4044           0 :         return NT_STATUS_OK;
    4045             : }
    4046             : 
    4047           0 : static bool test_smb1_qpathinfo(struct cli_state *cli)
    4048             : {
    4049           0 :         NTSTATUS status;
    4050           0 :         bool retval = false;
    4051           0 :         bool ok = false;
    4052           0 :         uint32_t attrs;
    4053             : 
    4054             :         /* Start clean. */
    4055           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\qpathinfo_file");
    4056             : 
    4057             :         /* Create a test file. */
    4058           0 :         ok = smb1_create_testfile(cli, "\\BAD\\BAD\\qpathinfo_file");
    4059           0 :         if (!ok) {
    4060           0 :                 printf("%s:%d failed to create test file %s\n",
    4061             :                         __FILE__,
    4062             :                         __LINE__,
    4063             :                         "\\BAD\\BAD\\qpathinfo_file");
    4064           0 :                 goto err;
    4065             :         }
    4066             : 
    4067             :         /* Should get root dir attrs. */
    4068           0 :         status = smb1_qpathinfo(cli, "qpathinfo_file", &attrs);
    4069           0 :         if (!NT_STATUS_IS_OK(status)) {
    4070           0 :                 printf("%s:%d smb1_qpathinfo failed %s (%s)\n",
    4071             :                         __FILE__,
    4072             :                         __LINE__,
    4073             :                         "qpathinfo_file",
    4074             :                         nt_errstr(status));
    4075           0 :                 goto err;
    4076             :         }
    4077           0 :         if ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0) {
    4078           0 :                 printf("%s:%d expected FILE_ATTRIBUTE_DIRECTORY on %s "
    4079             :                         "got attribute 0x%x\n",
    4080             :                         __FILE__,
    4081             :                         __LINE__,
    4082             :                         "qpathinfo_file",
    4083             :                         (unsigned int)attrs);
    4084           0 :                 goto err;
    4085             :         }
    4086             : 
    4087             :         /* Should get root dir attrs. */
    4088           0 :         status = smb1_qpathinfo(cli, "\\BAD\\qpathinfo_file", &attrs);
    4089           0 :         if (!NT_STATUS_IS_OK(status)) {
    4090           0 :                 printf("%s:%d smb1_qpathinfo failed %s (%s)\n",
    4091             :                         __FILE__,
    4092             :                         __LINE__,
    4093             :                         "\\BAD\\qpathinfo_file",
    4094             :                         nt_errstr(status));
    4095           0 :                 goto err;
    4096             :         }
    4097           0 :         if ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0) {
    4098           0 :                 printf("%s:%d expected FILE_ATTRIBUTE_DIRECTORY on %s "
    4099             :                         "got attribute 0x%x\n",
    4100             :                         __FILE__,
    4101             :                         __LINE__,
    4102             :                         "\\BAD\\qpathinfo_file",
    4103             :                         (unsigned int)attrs);
    4104           0 :                 goto err;
    4105             :         }
    4106             : 
    4107             :         /* Should get file attrs. */
    4108           0 :         status = smb1_qpathinfo(cli, "\\BAD\\BAD\\qpathinfo_file", &attrs);
    4109           0 :         if (!NT_STATUS_IS_OK(status)) {
    4110           0 :                 printf("%s:%d smb1_qpathinfo failed %s (%s)\n",
    4111             :                         __FILE__,
    4112             :                         __LINE__,
    4113             :                         "\\BAD\\BAD\\qpathinfo_file",
    4114             :                         nt_errstr(status));
    4115           0 :                 goto err;
    4116             :         }
    4117           0 :         if ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0) {
    4118           0 :                 printf("%s:%d expected not FILE_ATTRIBUTE_DIRECTORY on %s "
    4119             :                         "got attribute 0x%x\n",
    4120             :                         __FILE__,
    4121             :                         __LINE__,
    4122             :                         "\\BAD\\BAD\\qpathinfo_file",
    4123             :                         (unsigned int)attrs);
    4124             :         }
    4125             : 
    4126           0 :         retval = true;
    4127             : 
    4128           0 :   err:
    4129             : 
    4130           0 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\qpathinfo_file");
    4131           0 :         return retval;
    4132             : }
    4133             : 
    4134             : /*
    4135             :  * "Raw" test of different SMB1 operations to a DFS share.
    4136             :  * We must (mostly) use the lower level smb1cli_XXXX() interfaces,
    4137             :  * not the cli_XXX() ones here as the ultimate goal is to fix our
    4138             :  * cli_XXX() interfaces to work transparently over DFS.
    4139             :  *
    4140             :  * So here, we're testing the server code, not the client code.
    4141             :  *
    4142             :  * Passes cleanly against Windows.
    4143             :  */
    4144             : 
    4145           2 : bool run_smb1_dfs_operations(int dummy)
    4146             : {
    4147           2 :         struct cli_state *cli = NULL;
    4148           2 :         bool dfs_supported = false;
    4149           2 :         bool retval = false;
    4150           2 :         bool ok = false;
    4151             : 
    4152           2 :         printf("Starting SMB1-DFS-OPS\n");
    4153             : 
    4154           2 :         if (!torture_init_connection(&cli)) {
    4155           0 :                 return false;
    4156             :         }
    4157             : 
    4158           2 :         if (!torture_open_connection(&cli, 0)) {
    4159           0 :                 return false;
    4160             :         }
    4161             : 
    4162             :         /* Ensure this is a DFS share. */
    4163           2 :         dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
    4164           2 :         if (!dfs_supported) {
    4165           0 :                 printf("Server %s does not support DFS\n",
    4166           0 :                         smbXcli_conn_remote_name(cli->conn));
    4167           0 :                 return false;
    4168             :         }
    4169           2 :         dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb1.tcon);
    4170           2 :         if (!dfs_supported) {
    4171           0 :                 printf("Share %s does not support DFS\n",
    4172           0 :                         cli->share);
    4173           0 :                 return false;
    4174             :         }
    4175             : 
    4176           2 :         ok = test_smb1_unlink(cli);
    4177           2 :         if (!ok) {
    4178           0 :                 goto err;
    4179             :         }
    4180             : 
    4181           2 :         ok = test_smb1_mkdir(cli);
    4182           2 :         if (!ok) {
    4183           0 :                 goto err;
    4184             :         }
    4185             : 
    4186           2 :         ok = test_smb1_rmdir(cli);
    4187           2 :         if (!ok) {
    4188           0 :                 goto err;
    4189             :         }
    4190             : 
    4191           2 :         ok = test_smb1_ntcreatex(cli);
    4192           2 :         if (!ok) {
    4193           0 :                 goto err;
    4194             :         }
    4195             : 
    4196           2 :         ok = test_smb1_nttrans_create(cli);
    4197           2 :         if (!ok) {
    4198           0 :                 goto err;
    4199             :         }
    4200             : 
    4201           2 :         ok = test_smb1_openx(cli);
    4202           2 :         if (!ok) {
    4203           0 :                 goto err;
    4204             :         }
    4205             : 
    4206           2 :         ok = test_smb1_open(cli);
    4207           2 :         if (!ok) {
    4208           0 :                 goto err;
    4209             :         }
    4210             : 
    4211           2 :         ok = test_smb1_create(cli);
    4212           2 :         if (!ok) {
    4213           2 :                 goto err;
    4214             :         }
    4215             : 
    4216           0 :         ok = test_smb1_getatr(cli);
    4217           0 :         if (!ok) {
    4218           0 :                 goto err;
    4219             :         }
    4220             : 
    4221           0 :         ok = test_smb1_setatr(cli);
    4222           0 :         if (!ok) {
    4223           0 :                 goto err;
    4224             :         }
    4225             : 
    4226           0 :         ok = test_smb1_chkpath(cli);
    4227           0 :         if (!ok) {
    4228           0 :                 goto err;
    4229             :         }
    4230             : 
    4231           0 :         ok = test_smb1_ctemp(cli);
    4232           0 :         if (!ok) {
    4233           0 :                 goto err;
    4234             :         }
    4235             : 
    4236           0 :         ok = test_smb1_qpathinfo(cli);
    4237           0 :         if (!ok) {
    4238           0 :                 goto err;
    4239             :         }
    4240             : 
    4241           0 :         retval = true;
    4242             : 
    4243           2 :   err:
    4244             : 
    4245             :         /* Delete anything we made. */
    4246           2 :         (void)smb1_dfs_delete(cli, "\\BAD\\BAD\\file");
    4247           2 :         return retval;
    4248             : }
    4249             : 
    4250             : /*
    4251             :  * Test BUG: https://bugzilla.samba.org/show_bug.cgi?id=15419
    4252             :  */
    4253             : 
    4254           2 : bool run_smb1_dfs_check_badpath(int dummy)
    4255             : {
    4256           2 :         struct cli_state *cli = NULL;
    4257           2 :         bool dfs_supported = false;
    4258             : 
    4259           2 :         printf("Starting SMB1-DFS-CHECK-BADPATH\n");
    4260             : 
    4261           2 :         if (!torture_init_connection(&cli)) {
    4262           0 :                 return false;
    4263             :         }
    4264             : 
    4265           2 :         if (!torture_open_connection(&cli, 0)) {
    4266           0 :                 return false;
    4267             :         }
    4268             : 
    4269             :         /* Ensure this is a DFS share. */
    4270           2 :         dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
    4271           2 :         if (!dfs_supported) {
    4272           0 :                 printf("Server %s does not support DFS\n",
    4273           0 :                         smbXcli_conn_remote_name(cli->conn));
    4274           0 :                 return false;
    4275             :         }
    4276           2 :         dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb1.tcon);
    4277           2 :         if (!dfs_supported) {
    4278           0 :                 printf("Share %s does not support DFS\n",
    4279           0 :                         cli->share);
    4280           0 :                 return false;
    4281             :         }
    4282             : 
    4283           2 :         return test_smb1_chkpath_bad(cli);
    4284             : }

Generated by: LCOV version 1.14