s3: VFS: Add SMB_VFS_READ_DFS_PATHAT().
authorJeremy Allison <jra@samba.org>
Tue, 28 Jan 2020 17:51:17 +0000 (09:51 -0800)
committerRalph Boehme <slow@samba.org>
Tue, 18 Feb 2020 21:08:33 +0000 (21:08 +0000)
Not yet used.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_default.c
source3/modules/vfs_not_implemented.c
source3/smbd/vfs.c

index 71c34de801387a04be17edec49b7ee44383ef0ee..c1b5923b7523db35a8fae4ef0d258694715aa116 100644 (file)
@@ -112,6 +112,16 @@ static NTSTATUS skel_create_dfs_pathat(struct vfs_handle_struct *handle,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS skel_read_dfs_pathat(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *mem_ctx,
+                               struct files_struct *dirfsp,
+                               const struct smb_filename *smb_fname,
+                               struct referral **ppreflist,
+                               size_t *preferral_count)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
 static DIR *skel_opendir(vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        const char *mask,
@@ -1042,6 +1052,7 @@ static struct vfs_fn_pointers skel_opaque_fns = {
        .fs_capabilities_fn = skel_fs_capabilities,
        .get_dfs_referrals_fn = skel_get_dfs_referrals,
        .create_dfs_pathat_fn = skel_create_dfs_pathat,
+       .read_dfs_pathat_fn = skel_read_dfs_pathat,
        .snap_check_path_fn = skel_snap_check_path,
        .snap_create_fn = skel_snap_create,
        .snap_delete_fn = skel_snap_delete,
index 4b91f64f15ed92f61b637a6acb468e05fb8eca25..d2d05673fb439725d63d1d89a649282520f27b28 100644 (file)
@@ -113,6 +113,21 @@ static NTSTATUS skel_create_dfs_pathat(struct vfs_handle_struct *handle,
                                        referral_count);
 }
 
+static NTSTATUS skel_read_dfs_pathat(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *mem_ctx,
+                               struct files_struct *dirfsp,
+                               const struct smb_filename *smb_fname,
+                               struct referral **ppreflist,
+                               size_t *preferral_count)
+{
+       return SMB_VFS_NEXT_READ_DFS_PATHAT(handle,
+                                       mem_ctx,
+                                       dirfsp,
+                                       smb_fname,
+                                       ppreflist,
+                                       preferral_count);
+}
+
 static DIR *skel_opendir(vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        const char *mask,
@@ -1344,6 +1359,7 @@ static struct vfs_fn_pointers skel_transparent_fns = {
        .fs_capabilities_fn = skel_fs_capabilities,
        .get_dfs_referrals_fn = skel_get_dfs_referrals,
        .create_dfs_pathat_fn = skel_create_dfs_pathat,
+       .read_dfs_pathat_fn = skel_read_dfs_pathat,
        .snap_check_path_fn = skel_snap_check_path,
        .snap_create_fn = skel_snap_create,
        .snap_delete_fn = skel_snap_delete,
index 656fad8b5ee3bb12b6d305d892c99bb3019fc162..fec38f206443677bb77ca7f76906f595cdc3953d 100644 (file)
 /* Version 42 - Remove struct write_cache *wcp from files_struct */
 /* Version 42 - SMB_VFS_NTIMES() receives null times based on UTIMES_OMIT */
 /* Version 42 - Add SMB_VFS_CREATE_DFS_PATHAT() */
+/* Version 42 - Add SMB_VFS_READ_DFS_PATHAT() */
 
 #define SMB_VFS_INTERFACE_VERSION 42
 
@@ -716,6 +717,12 @@ struct vfs_fn_pointers {
                                const struct smb_filename *smb_fname,
                                const struct referral *reflist,
                                size_t referral_count);
+       NTSTATUS (*read_dfs_pathat_fn)(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *mem_ctx,
+                               struct files_struct *dirfsp,
+                               const struct smb_filename *smb_fname,
+                               struct referral **ppreflist,
+                               size_t *preferral_count);
 
        /* Directory operations */
 
@@ -1224,6 +1231,12 @@ NTSTATUS smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct *handle,
                                const struct smb_filename *smb_fname,
                                const struct referral *reflist,
                                size_t referral_count);
+NTSTATUS smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *mem_ctx,
+                               struct files_struct *dirfsp,
+                               const struct smb_filename *smb_fname,
+                               struct referral **ppreflist,
+                               size_t *preferral_count);
 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        const char *mask,
@@ -1666,6 +1679,12 @@ NTSTATUS vfs_not_implemented_create_dfs_pathat(struct vfs_handle_struct *handle,
                                const struct smb_filename *smb_fname,
                                const struct referral *reflist,
                                size_t referral_count);
+NTSTATUS vfs_not_implemented_read_dfs_pathat(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *mem_ctx,
+                               struct files_struct *dirfsp,
+                               const struct smb_filename *smb_fname,
+                               struct referral **ppreflist,
+                               size_t *preferral_count);
 DIR *vfs_not_implemented_opendir(vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        const char *mask,
index d4ccb8f5c731af98711c3274364569219cd7ecc3..112169ab83b81b08a6391596bee5ebb2d96e8639 100644 (file)
                (smb_fname), \
                (reflist), \
                (count))
+#define SMB_VFS_READ_DFS_PATHAT(conn, mem_ctx, dirfsp, smb_fname, ppreflist, pcount) \
+       smb_vfs_call_read_dfs_pathat((conn)->vfs_handles, \
+               (mem_ctx), \
+               (dirfsp), \
+               (smb_fname), \
+               (ppreflist), \
+               (pcount))
+#define SMB_VFS_NEXT_READ_DFS_PATHAT(handle, mem_ctx, dirfsp, smb_fname, ppreflist, pcount) \
+        smb_vfs_call_read_dfs_pathat((handle)->next, \
+               (mem_ctx), \
+                (dirfsp), \
+                (smb_fname), \
+                (ppreflist), \
+                (pcount))
 
 /* Directory operations */
 #define SMB_VFS_OPENDIR(conn, smb_fname, mask, attr) \
index f0c92f873e4b2c2104ce0f5608156dc4ca810369..37b59d8c3c061e741346d60000e4d1f796c6ac2f 100644 (file)
@@ -404,6 +404,108 @@ static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
        return status;
 }
 
+/*
+ * Read and return the contents of a DFS redirect given a
+ * pathname. A caller can pass in NULL for ppreflist and
+ * preferral_count but still determine if this was a
+ * DFS redirect point by getting NT_STATUS_OK back
+ * without incurring the overhead of reading and parsing
+ * the referral contents.
+ */
+
+static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *mem_ctx,
+                               struct files_struct *dirfsp,
+                               const struct smb_filename *smb_fname,
+                               struct referral **ppreflist,
+                               size_t *preferral_count)
+{
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
+       size_t bufsize;
+       char *link_target = NULL;
+       int referral_len;
+       bool ok;
+#if defined(HAVE_BROKEN_READLINK)
+       char link_target_buf[PATH_MAX];
+#else
+       char link_target_buf[7];
+#endif
+
+       SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
+
+       if (ppreflist == NULL && preferral_count == NULL) {
+               /*
+                * We're only checking if this is a DFS
+                * redirect. We don't need to return data.
+                */
+               bufsize = sizeof(link_target_buf);
+               link_target = link_target_buf;
+       } else {
+               bufsize = PATH_MAX;
+               link_target = talloc_array(mem_ctx, char, bufsize);
+               if (!link_target) {
+                       goto err;
+               }
+       }
+
+       referral_len = readlinkat(dirfsp->fh->fd,
+                               smb_fname->base_name,
+                               link_target,
+                               bufsize - 1);
+       if (referral_len == -1) {
+               if (errno == EINVAL) {
+                       /*
+                        * If the path isn't a link, readlinkat
+                        * returns EINVAL. Allow the caller to
+                        * detect this.
+                        */
+                       DBG_INFO("%s is not a link.\n", smb_fname->base_name);
+                       status = NT_STATUS_OBJECT_TYPE_MISMATCH;
+               } else {
+                       status = map_nt_error_from_unix(errno);
+                       DBG_ERR("Error reading "
+                               "msdfs link %s: %s\n",
+                               smb_fname->base_name,
+                               strerror(errno));
+               }
+                goto err;
+        }
+       link_target[referral_len] = '\0';
+
+       DBG_INFO("%s -> %s\n",
+                       smb_fname->base_name,
+                       link_target);
+
+       if (!strnequal(link_target, "msdfs:", 6)) {
+               status = NT_STATUS_OBJECT_TYPE_MISMATCH;
+               goto err;
+       }
+
+       if (ppreflist == NULL && preferral_count == NULL) {
+               /* Early return for checking if this is a DFS link. */
+               return NT_STATUS_OK;
+       }
+
+       ok = parse_msdfs_symlink(mem_ctx,
+                       lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
+                       link_target,
+                       ppreflist,
+                       preferral_count);
+
+       if (ok) {
+               status = NT_STATUS_OK;
+       } else {
+               status = NT_STATUS_NO_MEMORY;
+       }
+
+  err:
+
+       if (link_target != link_target_buf) {
+               TALLOC_FREE(link_target);
+       }
+       return status;
+}
+
 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
                                        TALLOC_CTX *mem_ctx,
                                        const char *service_path,
@@ -3517,6 +3619,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .fs_capabilities_fn = vfswrap_fs_capabilities,
        .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
        .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
+       .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
        .snap_check_path_fn = vfswrap_snap_check_path,
        .snap_create_fn = vfswrap_snap_create,
        .snap_delete_fn = vfswrap_snap_delete,
index 2bdab503d2c0b01a0f7af87307622eb41db9c391..5861e20d88d4558c92221dcfcacb4f2fc0877e51 100644 (file)
@@ -106,6 +106,16 @@ NTSTATUS vfs_not_implemented_create_dfs_pathat(struct vfs_handle_struct *handle,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+NTSTATUS vfs_not_implemented_read_dfs_pathat(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *mem_ctx,
+                               struct files_struct *dirfsp,
+                               const struct smb_filename *smb_fname,
+                               struct referral **ppreflist,
+                               size_t *preferral_count)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
 DIR *vfs_not_implemented_opendir(vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        const char *mask,
@@ -1047,6 +1057,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = {
        .fs_capabilities_fn = vfs_not_implemented_fs_capabilities,
        .get_dfs_referrals_fn = vfs_not_implemented_get_dfs_referrals,
        .create_dfs_pathat_fn = vfs_not_implemented_create_dfs_pathat,
+       .read_dfs_pathat_fn = vfs_not_implemented_read_dfs_pathat,
        .snap_check_path_fn = vfs_not_implemented_snap_check_path,
        .snap_create_fn = vfs_not_implemented_snap_create,
        .snap_delete_fn = vfs_not_implemented_snap_delete,
index e007a57fa011cf6a8441df0406f3d5f19f91f56e..7dc15158ccb614b1a206c0061bf78ff35c41dab9 100644 (file)
@@ -1577,6 +1577,22 @@ NTSTATUS smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct *handle,
                                                referral_count);
 }
 
+NTSTATUS smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *mem_ctx,
+                               struct files_struct *dirfsp,
+                               const struct smb_filename *smb_fname,
+                               struct referral **ppreflist,
+                               size_t *preferral_count)
+{
+       VFS_FIND(read_dfs_pathat);
+       return handle->fns->read_dfs_pathat_fn(handle,
+                                               mem_ctx,
+                                               dirfsp,
+                                               smb_fname,
+                                               ppreflist,
+                                               preferral_count);
+}
+
 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
                                        const struct smb_filename *smb_fname,
                                        const char *mask,