summaryrefslogtreecommitdiff
path: root/source3/modules
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-10-01 06:57:18 +0200
committerStefan Metzmacher <metze@samba.org>2011-10-08 01:43:38 +0200
commit9bd26d81900c16718e9ad3916aec5a7ac6b636be (patch)
tree80724d3c6a69c2cf9c793ca260a97754f9b839d6 /source3/modules
parent37a17a49175b2f0eca5578467b785325561eb0cf (diff)
downloadsamba-9bd26d81900c16718e9ad3916aec5a7ac6b636be.tar.gz
samba-9bd26d81900c16718e9ad3916aec5a7ac6b636be.tar.bz2
samba-9bd26d81900c16718e9ad3916aec5a7ac6b636be.zip
s3:vfs: add SMB_VFS_GET_DFS_REFERRAL() hooks
metze
Diffstat (limited to 'source3/modules')
-rw-r--r--source3/modules/vfs_default.c177
-rw-r--r--source3/modules/wscript_build2
2 files changed, 178 insertions, 1 deletions
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index d1bf95eb23..17200696b3 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -26,6 +26,8 @@
#include "smbprofile.h"
#include "../libcli/security/security.h"
#include "passdb/lookup_sid.h"
+#include "source3/include/msdfs.h"
+#include "librpc/gen_ndr/ndr_dfsblobs.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
@@ -165,6 +167,180 @@ static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
return caps;
}
+static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
+ struct dfs_GetDFSReferral *r)
+{
+ struct junction_map *junction = NULL;
+ int consumedcnt = 0;
+ bool self_referral = false;
+ char *pathnamep = NULL;
+ char *local_dfs_path = NULL;
+ NTSTATUS status;
+ int i;
+ uint16_t max_referral_level = r->in.req.max_referral_level;
+
+ if (DEBUGLVL(10)) {
+ NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
+ }
+
+ /* get the junction entry */
+ if (r->in.req.servername == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ /*
+ * Trim pathname sent by client so it begins with only one backslash.
+ * Two backslashes confuse some dfs clients
+ */
+
+ local_dfs_path = talloc_strdup(r, r->in.req.servername);
+ if (local_dfs_path == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ pathnamep = local_dfs_path;
+ while (IS_DIRECTORY_SEP(pathnamep[0]) &&
+ IS_DIRECTORY_SEP(pathnamep[1])) {
+ pathnamep++;
+ }
+
+ junction = talloc_zero(r, struct junction_map);
+ if (junction == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* The following call can change cwd. */
+ status = get_referred_path(r, pathnamep, handle->conn->sconn,
+ junction, &consumedcnt, &self_referral);
+ if (!NT_STATUS_IS_OK(status)) {
+ vfs_ChDir(handle->conn, handle->conn->connectpath);
+ return status;
+ }
+ vfs_ChDir(handle->conn, handle->conn->connectpath);
+
+ if (!self_referral) {
+ pathnamep[consumedcnt] = '\0';
+
+ if (DEBUGLVL(3)) {
+ dbgtext("setup_dfs_referral: Path %s to "
+ "alternate path(s):",
+ pathnamep);
+ for (i=0; i < junction->referral_count; i++) {
+ dbgtext(" %s",
+ junction->referral_list[i].alternate_path);
+ }
+ dbgtext(".\n");
+ }
+ }
+
+ if (r->in.req.max_referral_level <= 2) {
+ max_referral_level = 2;
+ }
+ if (r->in.req.max_referral_level >= 3) {
+ max_referral_level = 3;
+ }
+
+ r->out.resp = talloc_zero(r, struct dfs_referral_resp);
+ if (r->out.resp == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
+ r->out.resp->nb_referrals = junction->referral_count;
+
+ r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
+ if (self_referral) {
+ r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
+ }
+
+ r->out.resp->referral_entries = talloc_zero_array(r,
+ struct dfs_referral_type,
+ r->out.resp->nb_referrals);
+ if (r->out.resp->referral_entries == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ switch (max_referral_level) {
+ case 2:
+ for(i=0; i < junction->referral_count; i++) {
+ struct referral *ref = &junction->referral_list[i];
+ TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
+ struct dfs_referral_type *t =
+ &r->out.resp->referral_entries[i];
+ struct dfs_referral_v2 *v2 = &t->referral.v2;
+
+ t->version = 2;
+ v2->size = VERSION2_REFERRAL_SIZE;
+ if (self_referral) {
+ v2->server_type = DFS_SERVER_ROOT;
+ } else {
+ v2->server_type = DFS_SERVER_NON_ROOT;
+ }
+ v2->entry_flags = 0;
+ v2->proximity = ref->proximity;
+ v2->ttl = ref->ttl;
+ v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
+ if (v2->DFS_path == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
+ if (v2->DFS_alt_path == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ v2->netw_address = talloc_strdup(mem_ctx,
+ ref->alternate_path);
+ if (v2->netw_address == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ break;
+ case 3:
+ for(i=0; i < junction->referral_count; i++) {
+ struct referral *ref = &junction->referral_list[i];
+ TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
+ struct dfs_referral_type *t =
+ &r->out.resp->referral_entries[i];
+ struct dfs_referral_v3 *v3 = &t->referral.v3;
+ struct dfs_normal_referral *r1 = &v3->referrals.r1;
+
+ t->version = 3;
+ v3->size = VERSION3_REFERRAL_SIZE;
+ if (self_referral) {
+ v3->server_type = DFS_SERVER_ROOT;
+ } else {
+ v3->server_type = DFS_SERVER_NON_ROOT;
+ }
+ v3->entry_flags = 0;
+ v3->ttl = ref->ttl;
+ r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
+ if (r1->DFS_path == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
+ if (r1->DFS_alt_path == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ r1->netw_address = talloc_strdup(mem_ctx,
+ ref->alternate_path);
+ if (r1->netw_address == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ break;
+ default:
+ DEBUG(0,("setup_dfs_referral: Invalid dfs referral "
+ "version: %d\n",
+ max_referral_level));
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ if (DEBUGLVL(10)) {
+ NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
+ }
+
+ return NT_STATUS_OK;
+}
+
/* Directory operations */
static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
@@ -2002,6 +2178,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
.get_shadow_copy_data = vfswrap_get_shadow_copy_data,
.statvfs = vfswrap_statvfs,
.fs_capabilities = vfswrap_fs_capabilities,
+ .get_dfs_referrals = vfswrap_get_dfs_referrals,
/* Directory operations */
diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
index 2ae7a7e33a..b3ab734ac1 100644
--- a/source3/modules/wscript_build
+++ b/source3/modules/wscript_build
@@ -68,7 +68,7 @@ bld.SAMBA3_SUBSYSTEM('vfs',
bld.SAMBA3_MODULE('vfs_default',
subsystem='vfs',
source=VFS_DEFAULT_SRC,
- deps='samba-util',
+ deps='samba-util NDR_DFSBLOBS',
init_function='',
internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_default'),
enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_default'))