s3: libsmb: Add cli_dfs_target_check() function.
authorJeremy Allison <jra@samba.org>
Thu, 3 Feb 2022 19:15:30 +0000 (11:15 -0800)
committerNoel Power <npower@samba.org>
Fri, 4 Feb 2022 11:10:33 +0000 (11:10 +0000)
Strips any DFS prefix from a target name that will be passed
to an SMB1/2/3 rename or hardlink call. Returns a pointer
into the original target name after the prefix. Not yet used.

If the incoming filename is *NOT* a DFS prefix, the
original filename is returned unchanged.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14169

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Noel Power <npower@samba.org>
source3/libsmb/clidfs.c
source3/libsmb/proto.h

index 5b64858ca338ba5301b980962158a01689ab90fc..5288a7efc64d77589e48efc67468ff203c46bc5b 100644 (file)
@@ -1274,3 +1274,60 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 
        return true;
 }
+
+/********************************************************************
+ Windows and NetApp (and arguably the SMB1/2/3 specs) expect a non-DFS
+ path for the targets of rename and hardlink. If we have been given
+ a DFS path for these calls, convert it back into a local path by
+ stripping off the DFS prefix.
+********************************************************************/
+
+NTSTATUS cli_dfs_target_check(TALLOC_CTX *mem_ctx,
+                       struct cli_state *cli,
+                       const char *fname_src,
+                       const char *fname_dst,
+                       const char **fname_dst_out)
+{
+       char *dfs_prefix = NULL;
+       size_t prefix_len = 0;
+       struct smbXcli_tcon *tcon = NULL;
+
+       if (!smbXcli_conn_dfs_supported(cli->conn)) {
+               goto copy_fname_out;
+       }
+       if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+               tcon = cli->smb2.tcon;
+       } else {
+               tcon = cli->smb1.tcon;
+       }
+       if (!smbXcli_tcon_is_dfs_share(tcon)) {
+               goto copy_fname_out;
+       }
+       dfs_prefix = cli_dfs_make_full_path(mem_ctx, cli, "");
+       if (dfs_prefix == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       prefix_len = strlen(dfs_prefix);
+       if (strncmp(fname_dst, dfs_prefix, prefix_len) != 0) {
+               /*
+                * Prefix doesn't match. Assume it was
+                * already stripped or not added in the
+                * first place.
+                */
+               goto copy_fname_out;
+       }
+       /* Return the trailing name after the prefix. */
+       *fname_dst_out = &fname_dst[prefix_len];
+       TALLOC_FREE(dfs_prefix);
+       return NT_STATUS_OK;
+
+  copy_fname_out:
+
+       /*
+        * No change to the destination name. Just
+        * point it at the incoming destination name.
+        */
+       *fname_dst_out = fname_dst;
+       TALLOC_FREE(dfs_prefix);
+       return NT_STATUS_OK;
+}
index 8a32d4b7c2d28644f7c5a01f9b55382ebad9e077..bda4058dafe651bdf0bb38e7a892fd029ad0d72b 100644 (file)
@@ -160,6 +160,12 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
                        char **pp_newshare,
                        struct cli_credentials *creds);
 
+NTSTATUS cli_dfs_target_check(TALLOC_CTX *mem_ctx,
+                       struct cli_state *cli,
+                       const char *fname_src,
+                       const char *fname_dst,
+                       const char **fname_dst_out);
+
 /* The following definitions come from libsmb/clientgen.c  */
 
 unsigned int cli_set_timeout(struct cli_state *cli, unsigned int timeout);