From: Jeremy Allison Date: Thu, 3 Feb 2022 19:15:30 +0000 (-0800) Subject: s3: libsmb: Add cli_dfs_target_check() function. X-Git-Tag: tevent-0.12.0~782 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2abba0ea109d7a3a0b0cb4a7030293f70c2d9d8a;p=thirdparty%2Fsamba.git s3: libsmb: Add cli_dfs_target_check() function. 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 Reviewed-by: Noel Power --- diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 5b64858ca33..5288a7efc64 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -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; +} diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h index 8a32d4b7c2d..bda4058dafe 100644 --- a/source3/libsmb/proto.h +++ b/source3/libsmb/proto.h @@ -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);