diff options
author | Ralph Boehme <slow@samba.org> | 2014-11-26 14:30:37 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2014-12-04 22:11:07 +0100 |
commit | b65e37dc01d7afa007768f7cadfcf3b7c1007664 (patch) | |
tree | ec45710c1b260aedc21a4f5767f4465ab0817edd | |
parent | 46431e390f8184c4207f48704e0a0bb5dcb38366 (diff) | |
download | samba-b65e37dc01d7afa007768f7cadfcf3b7c1007664.tar.gz samba-b65e37dc01d7afa007768f7cadfcf3b7c1007664.tar.xz samba-b65e37dc01d7afa007768f7cadfcf3b7c1007664.zip |
s3:vfs: add SMB_VFS_READDIR_ATTR()
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>
-rw-r--r-- | examples/VFS/skel_opaque.c | 9 | ||||
-rw-r--r-- | examples/VFS/skel_transparent.c | 9 | ||||
-rw-r--r-- | source3/include/smb.h | 1 | ||||
-rw-r--r-- | source3/include/vfs.h | 10 | ||||
-rw-r--r-- | source3/include/vfs_macros.h | 5 | ||||
-rw-r--r-- | source3/lib/readdir_attr.h | 37 | ||||
-rw-r--r-- | source3/modules/vfs_default.c | 9 | ||||
-rw-r--r-- | source3/modules/vfs_full_audit.c | 18 | ||||
-rw-r--r-- | source3/modules/vfs_time_audit.c | 22 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 9 |
10 files changed, 129 insertions, 0 deletions
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 47b46a4db7..6e15a0675b 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -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. */ diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index fbb1323a6e..b11e29c342 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -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. */ diff --git a/source3/include/smb.h b/source3/include/smb.h index a6589dbac7..46e05c064d 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -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 { diff --git a/source3/include/vfs.h b/source3/include/vfs.h index e7dc07998d..b10e9a54be 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -159,6 +159,7 @@ /* 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); diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index e2d494dca6..df676adaca 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -565,4 +565,9 @@ (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 index 0000000000..d2a814dba3 --- /dev/null +++ b/source3/lib/readdir_attr.h @@ -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 */ diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 2ac7100cd7..7610e65906 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -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, diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index a51ab75815..489a28c58b 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -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, diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 9dbbf8bdea..243238a99e 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -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, diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 8e33f2d1a8..4b9696393a 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -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); +} |