From 77a942dd77e4034c08903b9fa9b5ffc1b319ebaf Mon Sep 17 00:00:00 2001 From: Sean Finney Date: Mon, 14 Mar 2011 10:51:06 +0000 Subject: [PATCH] Fix for Bug#8003: DFS proxy workaround for resolving against w2k8 In some scenarios (limited to win2k8 from our testing), attempting to resolve a DFS path with a Trans2 GET_DFS_REFERRAL request will fail if the path includes subdirectories not part of the DFS path. To work around this problem, if a server does not return any DFS referrals for a given share/path, try once again for the "split" path containing only the top-level share name. If this is successful, then follow the referral and append the "extra" split-off path back onto the path before returning to the caller. While a more robust solution is probably needed, it would likely require significant code shuffling and thus I leave that for someone more familiar with the code. The workaround should hopefully be acceptable in the meantime. --- source3/libsmb/clidfs.c | 49 +++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 47 insertions(+), 2 deletions(-) diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 345d0f9..2079f3b 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -992,7 +992,8 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, struct client_dfs_referral *refs = NULL; size_t num_refs = 0; size_t consumed = 0; - char *fullpath = NULL; + char *fullpath = NULL, *tmp_path = NULL; + char *tmp_server = NULL, *tmp_share = NULL, *tmp_extra = NULL; bool res; uint16 cnum; char *newextrapath = NULL; @@ -1044,7 +1045,46 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, cli->cnum = cnum; if (!res || !num_refs) { - return false; + /* In some domain-based DFS setups the server may not respond with DFS + * referrals for subfolders of a DFS root, it seems. To hack around + * this, try just one more time, but with just the sharename instead + * of the full share/extra. + */ + if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, "IPC$", "IPC", NULL, 0))) { + return false; + } + + if (force_encrypt) { + status = cli_cm_force_encryption(cli, + username, + password, + lp_workgroup(), + "IPC$"); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + } + + split_dfs_path(ctx, fullpath, &tmp_server, &tmp_share, &tmp_extra); + if ((tmp_server == NULL) || (tmp_share == NULL)) { + return false; + } + + tmp_path = talloc_asprintf(ctx, "\\%s\\%s", tmp_server, tmp_share); + if (tmp_path == NULL) { + return false; + } + + res = cli_dfs_get_referral(ctx, cli, tmp_path, &refs, &num_refs, &consumed); + status = cli_tdis(cli); + TALLOC_FREE(tmp_server); + TALLOC_FREE(tmp_share); + TALLOC_FREE(tmp_path); + + if (!NT_STATUS_IS_OK(status) || !res || !num_refs) { + TALLOC_FREE(tmp_extra); + return false; + } } if (!refs[0].dfspath) { @@ -1058,6 +1098,11 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, return false; } + if (tmp_extra != NULL) { + *pp_newshare = talloc_asprintf_append(*pp_newshare, "\\%s", tmp_extra); + TALLOC_FREE(tmp_extra); + } + /* check that this is not a self-referral */ if (strequal(cli->desthost, *pp_newserver) && -- 1.7.0.4