s3:vfs: add SMB_VFS_READDIR_ATTR()
authorRalph Boehme <slow@samba.org>
Wed, 26 Nov 2014 13:30:37 +0000 (14:30 +0100)
committerJeremy Allison <jra@samba.org>
Thu, 4 Dec 2014 21:11:07 +0000 (22:11 +0100)
SMB_VFS_READDIR_ATTR is a last minute hook to fetch additional metadata
for a directory entry when we're already marshalling the SMB reply
buffer.

This would be used, when there's a need to repurpose some fields in the
the reply, like it's done with Apple's SMB2 extension "AAPL".

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/smb.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/lib/readdir_attr.h [new file with mode: 0644]
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_time_audit.c
source3/smbd/vfs.c

index 47b46a4db756890be4d4ef3b23b1e45a6b8c99e9..6e15a0675b773c1876586d71532df0148b5e8d16 100644 (file)
@@ -633,6 +633,14 @@ static NTSTATUS skel_fsctl(struct vfs_handle_struct *handle,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS skel_readdir_attr(struct vfs_handle_struct *handle,
+                                 const struct smb_filename *fname,
+                                 TALLOC_CTX *mem_ctx,
+                                 struct readdir_attr_data **pattr_data)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
 static NTSTATUS skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                 uint32 security_info,
                                 TALLOC_CTX *mem_ctx,
@@ -896,6 +904,7 @@ struct vfs_fn_pointers skel_opaque_fns = {
        .strict_unlock_fn = skel_strict_unlock,
        .translate_name_fn = skel_translate_name,
        .fsctl_fn = skel_fsctl,
+       .readdir_attr_fn = skel_readdir_attr,
 
        /* NT ACL operations. */
 
index fbb1323a6ea639ebb6fa218400d2e1f6f5153536..b11e29c342a5c628981cbcb46c0be891fdd3f13b 100644 (file)
@@ -759,6 +759,14 @@ static NTSTATUS skel_fsctl(struct vfs_handle_struct *handle,
                                  in_len, _out_data, max_out_len, out_len);
 }
 
+static NTSTATUS skel_readdir_attr(struct vfs_handle_struct *handle,
+                                 const struct smb_filename *fname,
+                                 TALLOC_CTX *mem_ctx,
+                                 struct readdir_attr_data **pattr_data)
+{
+       return SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data);
+}
+
 static NTSTATUS skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                 uint32 security_info,
                                 TALLOC_CTX *mem_ctx,
@@ -1005,6 +1013,7 @@ struct vfs_fn_pointers skel_transparent_fns = {
        .strict_unlock_fn = skel_strict_unlock,
        .translate_name_fn = skel_translate_name,
        .fsctl_fn = skel_fsctl,
+       .readdir_attr_fn = skel_readdir_attr,
 
        /* NT ACL operations. */
 
index a6589dbac7c6ed93d53d3af07b51680c99decb38..46e05c064d584347ff1f62bcc4dd7366dcf1e9bb 100644 (file)
@@ -152,6 +152,7 @@ struct sys_notify_context {
 /* Include VFS stuff */
 
 #include "smb_acls.h"
+#include "lib/readdir_attr.h"
 #include "vfs.h"
 
 struct current_user {
index e7dc07998d521d2c172ce6e00410bab9f3158365..b10e9a54bee10f04e9170df033b536a888fb2789 100644 (file)
 /* Bump to version 32 - Samba 4.2 will ship with that. */
 /* Version 32 - Add "lease" to CREATE_FILE operation */
 /* Version 32 - Add "lease" to struct files_struct */
+/* Version 32 - Add SMB_VFS_READDIR_ATTR() */
 
 #define SMB_VFS_INTERFACE_VERSION 32
 
@@ -789,6 +790,11 @@ struct vfs_fn_pointers {
                                         TALLOC_CTX *mem_ctx,
                                         struct files_struct **fsp,
                                         DATA_BLOB *new_cookie);
+
+       NTSTATUS (*readdir_attr_fn)(struct vfs_handle_struct *handle,
+                                   const struct smb_filename *fname,
+                                   TALLOC_CTX *mem_ctx,
+                                   struct readdir_attr_data **attr_data);
 };
 
 /*
@@ -1234,6 +1240,10 @@ NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
                                        TALLOC_CTX *mem_ctx,
                                        struct files_struct **fsp,
                                        DATA_BLOB *new_cookie);
+NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
+                                  const struct smb_filename *fname,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct readdir_attr_data **attr_data);
 
 NTSTATUS smb_register_vfs(int version, const char *name,
                          const struct vfs_fn_pointers *fns);
index e2d494dca6ecf05ef5fcc5098599ec0e60be7cd8..df676adaca01443bc6c2e11526803104f4eb7902 100644 (file)
                                        (smb1req), (op), (old_cookie), \
                                        (mem_ctx), (fsp), (new_cookie))
 
+#define SMB_VFS_READDIR_ATTR(conn, fname, mem_ctx, attr_data) \
+       smb_vfs_call_readdir_attr((conn)->vfs_handles, (fname), (mem_ctx), (attr_data))
+#define SMB_VFS_NEXT_READDIR_ATTR(conn, fname, mem_ctx, attr_data) \
+       smb_vfs_call_readdir_attr((handle)->next, (fname), (mem_ctx), (attr_data))
+
 #endif /* _VFS_MACROS_H */
diff --git a/source3/lib/readdir_attr.h b/source3/lib/readdir_attr.h
new file mode 100644 (file)
index 0000000..d2a814d
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Fetch filesystem metadata in readdir/marshall context
+ *
+ * Copyright (C) Ralph Boehme 2014
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _READDIR_ATTR_H
+#define _READDIR_ATTR_H
+
+enum readdir_attr_type {RDATTR_NONE, RDATTR_AAPL};
+
+struct readdir_attr_data {
+       enum readdir_attr_type type;
+       union attr_data {
+               struct aapl {
+                       uint64_t rfork_size;
+                       char finder_info[16];
+                       uint32_t max_access;
+                       mode_t unix_mode;
+               } aapl;
+       } attr_data;
+};
+
+#endif /* _READDIR_ATTR_H */
index 2ac7100cd74834dcf83d155488d18d4ff6ce7ef4..7610e659064e4c7ba68411a7d31bc8ceea811bd0 100644 (file)
@@ -403,6 +403,14 @@ static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
        return result;
 }
 
+static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
+                                    const struct smb_filename *fname,
+                                    TALLOC_CTX *mem_ctx,
+                                    struct readdir_attr_data **attr_data)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
 {
        START_PROFILE(syscall_seekdir);
@@ -2521,6 +2529,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .opendir_fn = vfswrap_opendir,
        .fdopendir_fn = vfswrap_fdopendir,
        .readdir_fn = vfswrap_readdir,
+       .readdir_attr_fn = vfswrap_readdir_attr,
        .seekdir_fn = vfswrap_seekdir,
        .telldir_fn = vfswrap_telldir,
        .rewind_dir_fn = vfswrap_rewinddir,
index a51ab758154c40c36b06b702d3113164653e650b..489a28c58b3f4cad209e9678c71d44a65a3d65ce 100644 (file)
@@ -171,6 +171,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_COPY_CHUNK_RECV,
        SMB_VFS_OP_GET_COMPRESSION,
        SMB_VFS_OP_SET_COMPRESSION,
+       SMB_VFS_OP_READDIR_ATTR,
 
        /* NT ACL operations. */
 
@@ -295,6 +296,7 @@ static struct {
        { SMB_VFS_OP_COPY_CHUNK_RECV,   "copy_chunk_recv" },
        { SMB_VFS_OP_GET_COMPRESSION,   "get_compression" },
        { SMB_VFS_OP_SET_COMPRESSION,   "set_compression" },
+       { SMB_VFS_OP_READDIR_ATTR,      "readdir_attr" },
        { SMB_VFS_OP_FGET_NT_ACL,       "fget_nt_acl" },
        { SMB_VFS_OP_GET_NT_ACL,        "get_nt_acl" },
        { SMB_VFS_OP_FSET_NT_ACL,       "fset_nt_acl" },
@@ -1834,6 +1836,21 @@ static NTSTATUS smb_full_audit_set_compression(vfs_handle_struct *handle,
        return result;
 }
 
+static NTSTATUS smb_full_audit_readdir_attr(struct vfs_handle_struct *handle,
+                                           const struct smb_filename *fname,
+                                           TALLOC_CTX *mem_ctx,
+                                           struct readdir_attr_data **pattr_data)
+{
+       NTSTATUS status;
+
+       status = SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data);
+
+       do_log(SMB_VFS_OP_READDIR_ATTR, NT_STATUS_IS_OK(status), handle, "%s",
+              smb_fname_str_do_log(fname));
+
+       return status;
+}
+
 static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                           uint32 security_info,
                                           TALLOC_CTX *mem_ctx,
@@ -2249,6 +2266,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
        .copy_chunk_recv_fn = smb_full_audit_copy_chunk_recv,
        .get_compression_fn = smb_full_audit_get_compression,
        .set_compression_fn = smb_full_audit_set_compression,
+       .readdir_attr_fn = smb_full_audit_readdir_attr,
        .fget_nt_acl_fn = smb_full_audit_fget_nt_acl,
        .get_nt_acl_fn = smb_full_audit_get_nt_acl,
        .fset_nt_acl_fn = smb_full_audit_fset_nt_acl,
index 9dbbf8bdea9e23c940a8fc69b46325119a06b567..243238a99e76fe2a93c0feef8c9b5a7c50e10dda 100644 (file)
@@ -1802,6 +1802,27 @@ static NTSTATUS smb_time_audit_set_compression(vfs_handle_struct *handle,
        return result;
 }
 
+static NTSTATUS smb_time_audit_readdir_attr(struct vfs_handle_struct *handle,
+                                           const struct smb_filename *fname,
+                                           TALLOC_CTX *mem_ctx,
+                                           struct readdir_attr_data **pattr_data)
+{
+       NTSTATUS status;
+       struct timespec ts1,ts2;
+       double timediff;
+
+       clock_gettime_mono(&ts1);
+       status = SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data);
+       clock_gettime_mono(&ts2);
+       timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
+
+       if (timediff > audit_timeout) {
+               smb_time_audit_log_smb_fname("readdir_attr", timediff, fname);
+       }
+
+       return status;
+}
+
 static NTSTATUS smb_time_audit_fget_nt_acl(vfs_handle_struct *handle,
                                           files_struct *fsp,
                                           uint32 security_info,
@@ -2423,6 +2444,7 @@ static struct vfs_fn_pointers vfs_time_audit_fns = {
        .copy_chunk_recv_fn = smb_time_audit_copy_chunk_recv,
        .get_compression_fn = smb_time_audit_get_compression,
        .set_compression_fn = smb_time_audit_set_compression,
+       .readdir_attr_fn = smb_time_audit_readdir_attr,
        .fget_nt_acl_fn = smb_time_audit_fget_nt_acl,
        .get_nt_acl_fn = smb_time_audit_get_nt_acl,
        .fset_nt_acl_fn = smb_time_audit_fset_nt_acl,
index 8e33f2d1a838d9fe59d0d0d9c48f2ecffae40b81..4b9696393ab382b14d545244fb418dedd937395f 100644 (file)
@@ -2461,3 +2461,12 @@ NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
                                                 old_cookie, mem_ctx, fsp,
                                                 new_cookie);
 }
+
+NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
+                                  const struct smb_filename *fname,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct readdir_attr_data **attr_data)
+{
+       VFS_FIND(readdir_attr);
+       return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);
+}