smbclient: Fix recursive "ls" across DFS links
authorVolker Lendecke <vl@samba.org>
Mon, 19 Oct 2020 07:37:03 +0000 (09:37 +0200)
committerJeremy Allison <jra@samba.org>
Wed, 4 Nov 2020 18:55:40 +0000 (18:55 +0000)
This is an a bit subtle patch: The main trick is that the previous
code a DFS-style \\server\share\dir1\dir2 path ended up in the list of
directories to enumerate. This was then processed by do_list again,
passing it to cli_resolve_path. However, cli_resolve_path always
expects non-DFS style paths as input. This patch passes the original,
non-DFS path to do_list_helper(), so that it ends up without the DFS
style \\server\share prefix in the directory queue.

From general failure it just fails on the SMB1-based environments,
like the other smbclient_s3 ones in knownfail.d/smb1-tests

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
selftest/knownfail.d/recursive-dfs [deleted file]
selftest/knownfail.d/smb1-tests
source3/client/client.c

diff --git a/selftest/knownfail.d/recursive-dfs b/selftest/knownfail.d/recursive-dfs
deleted file mode 100644 (file)
index b5b809d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba3\.blackbox\.smbclient_s3\..*\.Recursive\ ls\ across\ MS-DFS\ links.*
index 28e78fa04272a319c113a635c938ea8d62ee9135..4ba1365b3a43edaddd0abfe4b355c39f1a5faa01 100644 (file)
@@ -30,6 +30,7 @@
 ^samba3.blackbox.smbclient_s3.NT1.(plain|sign).member_creds.rename_dotdot\((ad_member|nt4_member)\)
 ^samba3.blackbox.smbclient_s3.NT1.(plain|sign).member_creds.volume\((ad_member|nt4_member)\)
 ^samba3.blackbox.smbclient_s3.NT1.(plain|sign).member_creds.delete a non empty directory\((ad_member|nt4_member)\)
+^samba3.blackbox.smbclient_s3.NT1.(plain|sign).member_creds.Recursive ls across MS-DFS links\((ad_member|nt4_member)\)
 ^samba3.blackbox.smbclient_s3.*valid.users.nt4.*
 ^samba3.blackbox.smbclient_s3.NT1.*valid.users.*
 ^samba3.unix.whoami machine account.whoami\(ad_member:local\)
index ffcf8f5a62452542bd83e4134880aaa56c637d9a..45bfb18de1e2d1b3170bde5aa4035716568c8ed8 100644 (file)
@@ -585,6 +585,8 @@ static NTSTATUS display_finfo(struct cli_state *cli_state, struct file_info *fin
                        time_to_asc(t));
                dir_total += finfo->size;
        } else {
+               struct cli_state *targetcli = NULL;
+               char *targetpath = NULL;
                char *afname = NULL;
                uint16_t fnum;
 
@@ -605,9 +607,26 @@ static NTSTATUS display_finfo(struct cli_state *cli_state, struct file_info *fin
                d_printf( "MODE:%s\n", attrib_string(talloc_tos(), finfo->attr));
                d_printf( "SIZE:%.0f\n", (double)finfo->size);
                d_printf( "MTIME:%s", time_to_asc(t));
+
+               status = cli_resolve_path(
+                       ctx,
+                       "",
+                       get_cmdline_auth_info_creds(
+                               popt_get_cmdline_auth_info()),
+                       cli_state,
+                       afname,
+                       &targetcli,
+                       &targetpath);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DBG_WARNING("display_finfo() Failed to resolve "
+                                   "%s: %s\n",
+                                   afname, nt_errstr(status));
+                       return status;
+               }
+
                status = cli_ntcreate(
-                       cli_state,            /* cli */
-                       afname,               /* fname */
+                       targetcli,            /* cli */
+                       targetpath,           /* fname */
                        0,                    /* CreatFlags */
                        READ_CONTROL_ACCESS,  /* DesiredAccess */
                        0,                    /* FileAttributes */
@@ -623,7 +642,7 @@ static NTSTATUS display_finfo(struct cli_state *cli_state, struct file_info *fin
                                   afname, nt_errstr(status)));
                } else {
                        struct security_descriptor *sd = NULL;
-                       status = cli_query_secdesc(cli_state, fnum,
+                       status = cli_query_secdesc(targetcli, fnum,
                                                   ctx, &sd);
                        if (!NT_STATUS_IS_OK(status)) {
                                DEBUG( 0, ("display_finfo() failed to "
@@ -740,7 +759,6 @@ static NTSTATUS do_list_helper(
        char *dir_end = NULL;
        NTSTATUS status = NT_STATUS_OK;
        char *mask2 = NULL;
-       char *p = NULL;
 
        /* Work out the directory. */
        dir = talloc_strdup(ctx, state->mask);
@@ -780,23 +798,11 @@ static NTSTATUS do_list_helper(
        }
 
        mask2 = talloc_asprintf(ctx,
-                               "%s%s",
-                               mntpoint,
-                               mask);
-       if (!mask2) {
-               TALLOC_FREE(dir);
-               return NT_STATUS_NO_MEMORY;
-       }
-       p = strrchr_m(mask2,CLI_DIRSEP_CHAR);
-       if (p) {
-               p[1] = 0;
-       } else {
-               mask2[0] = '\0';
-       }
-       mask2 = talloc_asprintf_append(mask2,
-                                      "%s%s*",
-                                      f->name,
-                                      CLI_DIRSEP_STR);
+                               "%s%c%s%c*",
+                               dir,
+                               CLI_DIRSEP_CHAR,
+                               f->name,
+                               CLI_DIRSEP_CHAR);
        if (!mask2) {
                TALLOC_FREE(dir);
                return NT_STATUS_NO_MEMORY;
@@ -819,6 +825,7 @@ NTSTATUS do_list(const char *mask,
                        bool rec,
                        bool dirs)
 {
+       struct do_list_helper_state state = { .cli = cli, };
        static int in_do_list = 0;
        TALLOC_CTX *ctx = talloc_tos();
        struct cli_credentials *creds =
@@ -841,11 +848,11 @@ NTSTATUS do_list(const char *mask,
        add_to_do_list_queue(mask);
 
        while (!do_list_queue_empty()) {
-               struct do_list_helper_state state = {
-                       .mask = do_list_queue_head(),
-               };
+               struct cli_state *targetcli = NULL;
                char *targetpath = NULL;
 
+               state.mask = do_list_queue_head();
+
                /* check for dfs */
 
                status = cli_resolve_path(
@@ -854,7 +861,7 @@ NTSTATUS do_list(const char *mask,
                        creds,
                        cli,
                        state.mask,
-                       &state.cli,
+                       &targetcli,
                        &targetpath);
                if (!NT_STATUS_IS_OK(status)) {
                        d_printf("do_list: [%s] %s\n", state.mask,
@@ -864,7 +871,7 @@ NTSTATUS do_list(const char *mask,
                }
 
                status = cli_list(
-                       state.cli,
+                       targetcli,
                        targetpath,
                        attribute,
                        do_list_helper,